Merge pull request #3126 from manisandro/globe

Revived globe, compatible with OsgEarth 2.7
This commit is contained in:
Sandro Mani 2016-05-29 23:51:58 +02:00
commit 87121d63a8
102 changed files with 6125 additions and 6492 deletions

View File

@ -96,6 +96,9 @@ FIND_OSGEARTH_LIBRARY( OSGEARTHSYMBOLOGY_LIBRARY_DEBUG osgEarthSymbologyd )
FIND_OSGEARTH_LIBRARY( OSGEARTHQT_LIBRARY osgEarthQt )
FIND_OSGEARTH_LIBRARY( OSGEARTHQT_LIBRARY_DEBUG osgEarthQtd )
FIND_OSGEARTH_LIBRARY( OSGEARTHANNOTATION_LIBRARY osgEarthAnnotation )
FIND_OSGEARTH_LIBRARY( OSGEARTHANNOTATION_LIBRARY_DEBUG osgEarthAnnotationd )
SET( OSGEARTH_FOUND "NO" )
IF( OSGEARTH_LIBRARY AND OSGEARTH_INCLUDE_DIR )

View File

@ -522,6 +522,7 @@
<file>themes/default/symbologyRemove.svg</file>
<file>themes/default/symbologyUp.png</file>
<file>themes/default/symbologyUp.svg</file>
<file>themes/default/sync_views.svg</file>
<file>themes/default/text.png</file>
<file>themes/default/tracking.png</file>
<file>themes/default/transformed.png</file>

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="sync_views.svg">
<defs
id="defs4">
<linearGradient
inkscape:collect="always"
id="linearGradient4158">
<stop
style="stop-color:#0000ff;stop-opacity:1"
offset="0"
id="stop4160" />
<stop
style="stop-color:#0000a9;stop-opacity:1"
offset="1"
id="stop4162" />
</linearGradient>
<marker
inkscape:stockid="Arrow2Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4171"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) rotate(180) translate(0,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mend-8"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path4171-2"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(-0.6,-0.6)" />
</marker>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4158"
id="radialGradient4178"
cx="7.9999766"
cy="1040.8622"
fx="7.9999766"
fy="1040.8622"
r="6.9999766"
gradientTransform="matrix(1,0,0,0.49999621,0,520.43504)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4158"
id="radialGradient4178-3"
cx="7.9999766"
cy="1040.8622"
fx="7.9999766"
fy="1040.8622"
r="6.9999766"
gradientTransform="matrix(-1,0,0,0.49999621,16,527.43502)"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="18.5"
inkscape:cx="0.59568033"
inkscape:cy="10.721345"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="true"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:window-width="1600"
inkscape:window-height="829"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<g
id="g4865">
<path
style="fill:url(#radialGradient4178);fill-opacity:1;fill-rule:evenodd;stroke:#0000a9;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 1.5,1040.8622 0,1 8,0 0,2 5,-3 -5,-3 0,2 -8,0 z"
id="path4156"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<path
style="fill:url(#radialGradient4178-3);fill-opacity:1;fill-rule:evenodd;stroke:#0000a9;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 14.5,1047.8622 0,1 -7.9999996,0 0,2 -5,-3 5,-3 0,2 7.9999996,0 z"
id="path4156-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -24,6 +24,7 @@
%Include qgsaggregatecalculator.sip
%Include qgsattributeaction.sip
%Include qgsattributetableconfig.sip
%Include qgsbillboardregistry.sip
%Include qgsbrowsermodel.sip
%Include qgsclipper.sip
%Include qgscolorscheme.sip
@ -103,6 +104,7 @@
%Include qgsowsconnection.sip
%Include qgspaintenginehack.sip
%Include qgspallabeling.sip
%Include qgsplugininterface.sip
%Include qgspluginlayer.sip
%Include qgspluginlayerregistry.sip
%Include qgspoint.sip

View File

@ -0,0 +1,56 @@
/** Billboard items stored in the QgsBillBoardRegistry */
class QgsBillBoardItem
{
%TypeHeaderCode
#include <qgsbillboardregistry.h>
%End
public:
QImage image; /* The image of the billboard */
QgsPoint worldPos; /* The WGS84 world position of the billboard */
QString layerId; /* The layer which the image is part of, if any */
};
/**
* @brief The QgsBillBoardRegistry class stores images which should
* be displayed as billboards in the globe plugin.
* Map canvas items and layers may decide to add items which should
* be drawn as billboards in the globe.
*
* Retreive the instance pointer to a QgsBillBoardRegistry for a
* project via QgsProject::instance()->billboardRegistry().
*/
class QgsBillBoardRegistry : public QObject
{
%TypeHeaderCode
#include <qgsbillboardregistry.h>
%End
public:
/**
* @brief Adds a billboard to the registry
* @param parent The parent (i.e. a QgsMapLayer or a QgsMapCanvasItem) which is creating the billboard
* @param image The billboard image
* @param worldPos The geo position of the image, in WGS84
* @param layerId The id of the layer to which the item belongs, if any
*/
void addItem( void* parent, const QImage& image, const QgsPoint& worldPos, const QString& layerId = QString() );
/**
* @brief Removes all billboards which were created by the specified parent
* @param parent The parent
*/
void removeItem( void* parent );
/**
* @brief Retreive all registered billboard items
* @return List of registered billboard items
*/
QList<QgsBillBoardItem*> items() const;
signals:
/** Emitted when an item is added to the registry */
void itemAdded( QgsBillBoardItem* item );
/** Emitted when an item is removed from the registry */
void itemRemoved( QgsBillBoardItem* item );
private:
QgsBillBoardRegistry( QObject* parent = 0 );
};

View File

@ -66,6 +66,11 @@ class QgsMapSettings
//! @note added in 2.8
void setLayerStyleOverrides( const QMap<QString, QString>& overrides );
//! Get custom rendering flags, separated by ';'. Layers might honour these to alter their rendering.
const QString& customRenderFlags() const;
//! Set custom rendering flags, separated by ';'. Layers might honour these to alter their rendering.
void setCustomRenderFlags( const QString& customRenderFlags );
//! sets whether to use projections for this layer set
void setCrsTransformEnabled( bool enabled );
//! returns true if projections are enabled for this layer set

View File

@ -0,0 +1,28 @@
/***************************************************************************
qgsplugininterface.sip
--------------------------------------
Date : 21.8.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/**
* @brief Trivial base class for plugin interfaces
*/
class QgsPluginInterface : QObject
{
%TypeHeaderCode
#include "qgsplugininterface.h"
%End
protected:
/** Should only be instantiated from subclasses */
QgsPluginInterface( QObject* parent = 0 );
};

View File

@ -275,6 +275,11 @@ class QgsProject : QObject
QgsRelationManager* relationManager() const;
/** Return the project's billboard manager instance pointer
* @note added in QGIS 2.16
*/
QgsBillBoardRegistry* billboardRegistry() const;
/** Return pointer to the root (invisible) node of the project's layer tree
* @note added in 2.4
*/

View File

@ -74,7 +74,7 @@ class QgsRectangle
//! return true when rectangle contains a point
bool contains( const QgsPoint &p ) const;
//! expand the rectangle so that covers both the original rectangle and the given rectangle
void combineExtentWith( QgsRectangle *rect );
void combineExtentWith( const QgsRectangle& rect );
//! expand the rectangle so that covers both the original rectangle and the given point
void combineExtentWith( double x, double y );
//! test if rectangle is empty.

View File

@ -102,6 +102,7 @@
%Include qgsmaplayeractionregistry.sip
%Include qgsmaplayercombobox.sip
%Include qgsmaplayermodel.sip
%Include qgsmaplayerpropertiesfactory.sip
%Include qgsmaplayerproxymodel.sip
%Include qgsmapmouseevent.sip
%Include qgsmapoverviewcanvas.sip
@ -155,6 +156,7 @@
%Include qgsunitselectionwidget.sip
%Include qgsuserinputdockwidget.sip
%Include qgsvariableeditorwidget.sip
%Include qgsvectorlayerpropertiespage.sip
%Include qgsvectorlayertools.sip
%Include qgsvertexmarker.sip

View File

@ -279,6 +279,12 @@ class QgisInterface : QObject
/** Unregister a previously registered action. (e.g. when plugin is going to be unloaded) */
virtual bool unregisterMainWindowAction( QAction* action ) = 0;
/** Register a new tab in the vector layer properties dialog */
virtual void registerMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory ) = 0;
/** Unregister a previously registered tab in the layer properties dialog */
virtual void unregisterMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory ) = 0;
// @todo is this deprecated in favour of QgsContextHelp?
/** Open a url in the users browser. By default the QGIS doc directory is used
* as the base for the URL. To open a URL that is not relative to the installed

View File

@ -0,0 +1,32 @@
/** \ingroup gui
* \note added in 2.1
*/
class QgsMapLayerPropertiesFactory
{
%TypeHeaderCode
#include <qgsmaplayerpropertiesfactory.h>
%End
public:
/** Constructor */
QgsMapLayerPropertiesFactory();
/** Destructor */
virtual ~QgsMapLayerPropertiesFactory();
/**
* @brief Create a new properties page
* @param layer The layer for which to create the page
* @param parent The parent widget
* @return The new properties page instance
*/
virtual QgsVectorLayerPropertiesPage* createVectorLayerPropertiesPage( QgsVectorLayer* layer, QWidget* parent ) = 0;
/**
* @brief Creates the QListWidgetItem for the properties page
* @param layer The layer for which to create the item
* @param view The parent QListView
* @return The QListWidgetItem for the properties page
*/
virtual QListWidgetItem* createVectorLayerPropertiesItem( QgsVectorLayer* layer, QListWidget* view ) = 0;
};

View File

@ -0,0 +1,21 @@
/** \ingroup gui
* \note added in 2.1
*/
/**
* @brief Base class for custom vector layer property pages
*/
class QgsVectorLayerPropertiesPage : QWidget
{
%TypeHeaderCode
#include <qgsvectorlayerpropertiespage.h>
%End
public:
/** Constructor */
explicit QgsVectorLayerPropertiesPage( QWidget *parent = 0 );
public slots:
/** Apply changes */
virtual void apply() = 0;
};

View File

@ -8810,6 +8810,16 @@ void QgisApp::openURL( QString url, bool useQgisDocDirectory )
#endif
}
void QgisApp::registerMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory )
{
mMapLayerPropertiesFactories << factory;
}
void QgisApp::unregisterMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory )
{
mMapLayerPropertiesFactories.removeAll( factory );
}
/** Get a pointer to the currently selected map layer */
QgsMapLayer *QgisApp::activeLayer()
{
@ -11021,6 +11031,10 @@ void QgisApp::showLayerProperties( QgsMapLayer *ml )
#else
QgsVectorLayerProperties *vlp = new QgsVectorLayerProperties( vlayer, this );
#endif
foreach ( QgsMapLayerPropertiesFactory* factory, mMapLayerPropertiesFactories )
{
vlp->addPropertiesPageFactory( factory );
}
if ( vlp->exec() )
{

View File

@ -56,6 +56,7 @@ class QgsLayerTreeMapCanvasBridge;
class QgsLayerTreeView;
class QgsMapCanvas;
class QgsMapLayer;
class QgsMapLayerPropertiesFactory;
class QgsMapTip;
class QgsMapTool;
class QgsMapToolAdvancedDigitizing;
@ -501,6 +502,12 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
void parseVersionInfo( QNetworkReply* reply, int& latestVersion, QStringList& versionInfo );
/** Register a new tab in the layer properties dialog */
void registerMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory );
/** Unregister a previously registered tab in the layer properties dialog */
void unregisterMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory );
public slots:
void layerTreeViewDoubleClicked( const QModelIndex& index );
//! Make sure the insertion point for new layers is up-to-date with the current item in layer tree view
@ -1745,6 +1752,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsSnappingUtils* mSnappingUtils;
QList<QgsMapLayerPropertiesFactory*> mMapLayerPropertiesFactories;
QDateTime mProjectLastModified;
QgsWelcomePage* mWelcomePage;

View File

@ -475,6 +475,16 @@ bool QgisAppInterface::unregisterMainWindowAction( QAction* action )
return QgsShortcutsManager::instance()->unregisterAction( action );
}
void QgisAppInterface::registerMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory )
{
qgis->registerMapLayerPropertiesFactory( factory );
}
void QgisAppInterface::unregisterMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory )
{
qgis->unregisterMapLayerPropertiesFactory( factory );
}
//! Menus
Q_DECL_DEPRECATED QMenu *QgisAppInterface::fileMenu() { return qgis->projectMenu(); }
QMenu *QgisAppInterface::projectMenu() { return qgis->projectMenu(); }

View File

@ -288,6 +288,12 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
/** Unregister a previously registered action. (e.g. when plugin is going to be unloaded. */
virtual bool unregisterMainWindowAction( QAction* action ) override;
/** Register a new tab in the layer properties dialog */
virtual void registerMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory ) override;
/** Unregister a previously registered tab in the layer properties dialog */
virtual void unregisterMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory ) override;
/** Accessors for inserting items into menus and toolbars.
* An item can be inserted before any existing action.
*/

View File

@ -35,6 +35,7 @@
#include "qgslabel.h"
#include "qgsgenericprojectionselector.h"
#include "qgslogger.h"
#include "qgsmaplayerpropertiesfactory.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaplayerstyleguiutils.h"
#include "qgspluginmetadata.h"
@ -44,6 +45,7 @@
#include "qgsloadstylefromdbdialog.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerproperties.h"
#include "qgsvectorlayerpropertiespage.h"
#include "qgsconfig.h"
#include "qgsvectordataprovider.h"
#include "qgsquerybuilder.h"
@ -323,6 +325,19 @@ void QgsVectorLayerProperties::setLabelCheckBox()
labelCheckBox->setCheckState( Qt::Checked );
}
void QgsVectorLayerProperties::addPropertiesPageFactory( QgsMapLayerPropertiesFactory* factory )
{
QListWidgetItem* item = factory->createVectorLayerPropertiesItem( mLayer, mOptionsListWidget );
if ( item )
{
mOptionsListWidget->addItem( item );
QgsVectorLayerPropertiesPage* page = factory->createVectorLayerPropertiesPage( mLayer, this );
mLayerPropertiesPages << page;
mOptionsStackedWidget->addWidget( page );
}
}
void QgsVectorLayerProperties::insertField()
{
// Convert the selected field to an expression and
@ -606,6 +621,12 @@ void QgsVectorLayerProperties::apply()
//apply diagram settings
diagramPropertiesDialog->apply();
// apply all plugin dialogs
foreach ( QgsVectorLayerPropertiesPage* page, mLayerPropertiesPages )
{
page->apply();
}
//layer title and abstract
mLayer->setShortName( mLayerShortNameLineEdit->text() );
mLayer->setTitle( mLayerTitleLineEdit->text() );

View File

@ -42,6 +42,8 @@ class QgsLabelingWidget;
class QgsDiagramProperties;
class QgsFieldsProperties;
class QgsRendererV2PropertiesDialog;
class QgsMapLayerPropertiesFactory;
class QgsVectorLayerPropertiesPage;
class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private Ui::QgsVectorLayerPropertiesBase
{
@ -74,6 +76,9 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private
@return false in case of a non-existing attribute.*/
bool deleteAttribute( int attr );
/** Adds a properties page factory to the vector layer properties dialog. */
void addPropertiesPageFactory( QgsMapLayerPropertiesFactory *factory );
public slots:
/** Insert a field in the expression text for the map tip **/
@ -190,6 +195,9 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private
//! List of joins of a layer at the time of creation of the dialog. Used to return joins to previous state if dialog is cancelled
QList< QgsVectorJoinInfo > mOldJoins;
//! A list of additional pages provided by plugins
QList<QgsVectorLayerPropertiesPage*> mLayerPropertiesPages;
/** Previous layer style. Used to reset style to previous state if new style
* was loaded but dialog is cancelled */
QgsMapLayerStyle mOldStyle;

View File

@ -81,6 +81,7 @@ SET(QGIS_CORE_SRCS
qgsactionmanager.cpp
qgsaggregatecalculator.cpp
qgsattributetableconfig.cpp
qgsbillboardregistry.cpp
qgsbrowsermodel.cpp
qgscachedfeatureiterator.cpp
qgscacheindex.cpp
@ -167,6 +168,7 @@ SET(QGIS_CORE_SRCS
qgspallabeling.cpp
qgspluginlayer.cpp
qgspluginlayerregistry.cpp
qgsplugininterface.cpp
qgspoint.cpp
qgspointlocator.cpp
qgsproject.cpp
@ -449,6 +451,7 @@ ENDIF(NOT MSVC)
SET(QGIS_CORE_MOC_HDRS
qgsapplication.h
qgsbillboardregistry.h
qgsbrowsermodel.h
qgscontexthelp.h
qgscoordinatetransform.h
@ -479,6 +482,7 @@ SET(QGIS_CORE_MOC_HDRS
qgsofflineediting.h
qgsowsconnection.h
qgspluginlayer.h
qgsplugininterface.h
qgspointlocator.h
qgsproject.h
qgsrelationmanager.h

View File

@ -3706,7 +3706,7 @@ QgsRectangle QgsDxfExport::dxfExtent() const
else
{
QgsRectangle layerExtent = layerIt->first->extent();
extent.combineExtentWith( &layerExtent );
extent.combineExtentWith( layerExtent );
}
}
}

View File

@ -78,7 +78,7 @@ QgsRectangle QgsCircularStringV2::calculateBoundingBox() const
else
{
QgsRectangle segmentBox = segmentBoundingBox( QgsPointV2( mX[i], mY[i] ), QgsPointV2( mX[i + 1], mY[i + 1] ), QgsPointV2( mX[i + 2], mY[i + 2] ) );
bbox.combineExtentWith( &segmentBox );
bbox.combineExtentWith( segmentBox );
}
}

View File

@ -95,7 +95,7 @@ QgsRectangle QgsCompoundCurveV2::calculateBoundingBox() const
for ( int i = 1; i < mCurves.size(); ++i )
{
QgsRectangle curveBox = mCurves.at( i )->boundingBox();
bbox.combineExtentWith( &curveBox );
bbox.combineExtentWith( curveBox );
}
return bbox;
}

View File

@ -336,7 +336,7 @@ QgsRectangle QgsGeometryCollectionV2::calculateBoundingBox() const
for ( int i = 1; i < mGeometries.size(); ++i )
{
QgsRectangle geomBox = mGeometries.at( i )->boundingBox();
bbox.combineExtentWith( &geomBox );
bbox.combineExtentWith( geomBox );
}
return bbox;
}

View File

@ -0,0 +1,42 @@
/***************************************************************************
qgsbillboardregistry.cpp
------------------------
begin : February 2016
copyright : (C) 2016 by Sandro Mani
email : smani@sourcepole.ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsbillboardregistry.h"
void QgsBillBoardRegistry::addItem( void* parent, const QImage &image, const QgsPoint &worldPos , const QString &layerId )
{
QMap<void*, QgsBillBoardItem*>::iterator it = mItems.find( parent );
if ( it == mItems.end() )
{
it = mItems.insert( parent, new QgsBillBoardItem );
}
it.value()->image = image;
it.value()->worldPos = worldPos;
it.value()->layerId = layerId;
emit itemAdded( it.value() );
}
void QgsBillBoardRegistry::removeItem( void* parent )
{
emit itemRemoved( mItems[parent] );
delete mItems.take( parent );
}
QList<QgsBillBoardItem*> QgsBillBoardRegistry::items() const
{
return mItems.values();
}

View File

@ -0,0 +1,82 @@
/***************************************************************************
qgsbillboardregistry.h
----------------------
begin : February 2016
copyright : (C) 2016 by Sandro Mani
email : smani@sourcepole.ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSBILLBOARDREGISTRY_H
#define QGSBILLBOARDREGISTRY_H
#include <QObject>
#include <QImage>
#include "qgspoint.h"
class QgsMapCanvasItem;
/** Billboard items stored in the QgsBillBoardRegistry */
class CORE_EXPORT QgsBillBoardItem
{
public:
QImage image; /* The image of the billboard */
QgsPoint worldPos; /* The WGS84 world position of the billboard */
QString layerId; /* The layer which the image is part of, if any */
};
/**
* @brief The QgsBillBoardRegistry class stores images which should
* be displayed as billboards in the globe plugin.
* Map canvas items and layers may decide to add items which should
* be drawn as billboards in the globe.
*
* Retreive the instance pointer to a QgsBillBoardRegistry for a
* project via QgsProject::instance()->billboardRegistry().
*/
class CORE_EXPORT QgsBillBoardRegistry : public QObject
{
Q_OBJECT
public:
/**
* @brief Adds a billboard to the registry
* @param parent The parent (i.e. a QgsMapLayer or a QgsMapCanvasItem) which is creating the billboard
* @param image The billboard image
* @param worldPos The geo position of the image, in WGS84
* @param layerId The id of the layer to which the item belongs, if any
*/
void addItem( void* parent, const QImage& image, const QgsPoint& worldPos, const QString& layerId = QString() );
/**
* @brief Removes all billboards which were created by the specified parent
* @param parent The parent
*/
void removeItem( void* parent );
/**
* @brief Retreive all registered billboard items
* @return List of registered billboard items
*/
QList<QgsBillBoardItem*> items() const;
signals:
/** Emitted when an item is added to the registry */
void itemAdded( QgsBillBoardItem* item );
/** Emitted when an item is removed from the registry */
void itemRemoved( QgsBillBoardItem* item );
private:
friend class QgsProject; // Only QgsProject is allowed to construct this class
QgsBillBoardRegistry( QObject* parent = 0 ) : QObject( parent ) {}
QMap<void*, QgsBillBoardItem*> mItems;
};
#endif // QGSBILLBOARDREGISTRY_H

View File

@ -114,6 +114,11 @@ class CORE_EXPORT QgsMapSettings
//! @note added in 2.8
void setLayerStyleOverrides( const QMap<QString, QString>& overrides );
//! Get custom rendering flags, separated by ';'. Layers might honour these to alter their rendering.
const QString& customRenderFlags() const { return mCustomRenderFlags; }
//! Set custom rendering flags, separated by ';'. Layers might honour these to alter their rendering.
void setCustomRenderFlags( const QString& customRenderFlags ) { mCustomRenderFlags = customRenderFlags; }
//! sets whether to use projections for this layer set
void setCrsTransformEnabled( bool enabled );
//! returns true if projections are enabled for this layer set
@ -290,6 +295,7 @@ class CORE_EXPORT QgsMapSettings
QStringList mLayers;
QMap<QString, QString> mLayerStyleOverrides;
QString mCustomRenderFlags;
QgsExpressionContext mExpressionContext;
bool mProjectionsEnabled;

View File

View File

@ -0,0 +1,33 @@
/***************************************************************************
qgsplugininterface.h
--------------------------------------
Date : 21.8.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSPLUGININTERFACE_H
#define QGSPLUGININTERFACE_H
#include <QObject>
/**
* @brief Trivial base class for plugin interfaces
*/
class CORE_EXPORT QgsPluginInterface : public QObject
{
Q_OBJECT
protected:
/** Should only be instantiated from subclasses */
QgsPluginInterface( QObject* parent = 0 ) : QObject( parent ) {}
};
#endif // QGSPLUGININTERFACE_H

View File

@ -17,6 +17,7 @@
#include "qgsproject.h"
#include "qgsbillboardregistry.h"
#include "qgsdatasourceuri.h"
#include "qgsexception.h"
#include "qgslayertree.h"
@ -361,6 +362,7 @@ QgsProject::QgsProject()
, mBadLayerHandler( new QgsProjectBadLayerDefaultHandler() )
, mRelationManager( new QgsRelationManager( this ) )
, mRootGroup( new QgsLayerTreeGroup )
, mBillboardRegistry( new QgsBillBoardRegistry( this ) )
{
clear();

View File

@ -41,6 +41,7 @@ class QDomDocument;
class QDomElement;
class QDomNode;
class QgsBillBoardRegistry;
class QgsLayerTreeGroup;
class QgsLayerTreeRegistryBridge;
class QgsMapLayer;
@ -323,6 +324,11 @@ class CORE_EXPORT QgsProject : public QObject
QgsRelationManager* relationManager() const;
/** Return the project's billboard manager instance pointer
* @note added in QGIS 2.16
*/
QgsBillBoardRegistry* billboardRegistry() const { return mBillboardRegistry; }
/** Return pointer to the root (invisible) node of the project's layer tree
* @note added in 2.4
*/
@ -487,6 +493,8 @@ class CORE_EXPORT QgsProject : public QObject
QgsLayerTreeRegistryBridge* mLayerTreeRegistryBridge;
QgsBillBoardRegistry* mBillboardRegistry;
//! map of transaction group: QPair( providerKey, connString ) -> transactionGroup
QMap< QPair< QString, QString>, QgsTransactionGroup*> mTransactionGroups;

View File

@ -194,14 +194,14 @@ bool QgsRectangle::contains( const QgsPoint &p ) const
ymin <= p.y() && p.y() <= ymax;
}
void QgsRectangle::combineExtentWith( QgsRectangle * rect )
void QgsRectangle::combineExtentWith( const QgsRectangle &rect )
{
xmin = (( xmin < rect->xMinimum() ) ? xmin : rect->xMinimum() );
xmax = (( xmax > rect->xMaximum() ) ? xmax : rect->xMaximum() );
xmin = (( xmin < rect.xMinimum() ) ? xmin : rect.xMinimum() );
xmax = (( xmax > rect.xMaximum() ) ? xmax : rect.xMaximum() );
ymin = (( ymin < rect->yMinimum() ) ? ymin : rect->yMinimum() );
ymax = (( ymax > rect->yMaximum() ) ? ymax : rect->yMaximum() );
ymin = (( ymin < rect.yMinimum() ) ? ymin : rect.yMinimum() );
ymax = (( ymax > rect.yMaximum() ) ? ymax : rect.yMaximum() );
}

View File

@ -97,7 +97,7 @@ class CORE_EXPORT QgsRectangle
//! return true when rectangle contains a point
bool contains( const QgsPoint &p ) const;
//! expand the rectangle so that covers both the original rectangle and the given rectangle
void combineExtentWith( QgsRectangle *rect );
void combineExtentWith( const QgsRectangle& rect );
//! expand the rectangle so that covers both the original rectangle and the given point
void combineExtentWith( double x, double y );
//! test if rectangle is empty.

View File

@ -717,7 +717,7 @@ QgsRectangle QgsVectorLayer::boundingBoxOfSelected()
if ( !fet.constGeometry() || fet.constGeometry()->isEmpty() )
continue;
r = fet.constGeometry()->boundingBox();
retval.combineExtentWith( &r );
retval.combineExtentWith( r );
}
}
else
@ -732,7 +732,7 @@ QgsRectangle QgsVectorLayer::boundingBoxOfSelected()
if ( fet.constGeometry() )
{
r = fet.constGeometry()->boundingBox();
retval.combineExtentWith( &r );
retval.combineExtentWith( r );
}
}
}
@ -1000,7 +1000,7 @@ QgsRectangle QgsVectorLayer::extent()
if ( mDataProvider->featureCount() != 0 )
{
QgsRectangle r = mDataProvider->extent();
rect.combineExtentWith( &r );
rect.combineExtentWith( r );
}
if ( mEditBuffer )
@ -1010,7 +1010,7 @@ QgsRectangle QgsVectorLayer::extent()
if ( it->constGeometry() )
{
QgsRectangle r = it->constGeometry()->boundingBox();
rect.combineExtentWith( &r );
rect.combineExtentWith( r );
}
}
}
@ -1026,7 +1026,7 @@ QgsRectangle QgsVectorLayer::extent()
if ( fet.constGeometry() && fet.constGeometry()->type() != QGis::UnknownGeometry )
{
QgsRectangle bb = fet.constGeometry()->boundingBox();
rect.combineExtentWith( &bb );
rect.combineExtentWith( bb );
}
}
}

View File

@ -239,6 +239,7 @@ SET(QGIS_GUI_SRCS
qgsmaplayeractionregistry.cpp
qgsmaplayercombobox.cpp
qgsmaplayermodel.cpp
qgsmaplayerpropertiesfactory.cpp
qgsmaplayerproxymodel.cpp
qgsmapmouseevent.cpp
qgsmapoverviewcanvas.cpp
@ -292,6 +293,7 @@ SET(QGIS_GUI_SRCS
qgsunitselectionwidget.cpp
qgsuserinputdockwidget.cpp
qgsvariableeditorwidget.cpp
qgsvectorlayerpropertiespage.cpp
qgsvertexmarker.cpp
)
@ -431,6 +433,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsunitselectionwidget.h
qgsuserinputdockwidget.h
qgsvariableeditorwidget.h
qgsvectorlayerpropertiespage.h
raster/qgsmultibandcolorrendererwidget.h
raster/qgspalettedrendererwidget.h

View File

@ -617,7 +617,7 @@ void QgsRelationReferenceWidget::highlightFeature( QgsFeature f, CanvasExtent ca
QgsRectangle extent = mCanvas->extent();
if ( !extent.contains( featBBox ) )
{
extent.combineExtentWith( &featBBox );
extent.combineExtentWith( featBBox );
extent.scale( 1.1 );
mCanvas->setExtent( extent );
mCanvas->refresh();

View File

@ -242,7 +242,7 @@ void QgsLayerTreeViewDefaultActions::zoomToLayers( QgsMapCanvas* canvas, const Q
if ( canvas->hasCrsTransformEnabled() )
layerExtent = canvas->mapSettings().layerExtentToOutputExtent( layer, layerExtent );
extent.combineExtentWith( &layerExtent );
extent.combineExtentWith( layerExtent );
}
if ( extent.isNull() )

View File

@ -34,6 +34,7 @@ class QgsLayerTreeView;
class QgsLegendInterface;
class QgsMapCanvas;
class QgsMapLayer;
class QgsMapLayerPropertiesFactory;
class QgsMessageBar;
class QgsPluginManagerInterface;
class QgsRasterLayer;
@ -328,6 +329,12 @@ class GUI_EXPORT QgisInterface : public QObject
/** Unregister a previously registered action. (e.g. when plugin is going to be unloaded) */
virtual bool unregisterMainWindowAction( QAction* action ) = 0;
/** Register a new tab in the vector layer properties dialog */
virtual void registerMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory ) = 0;
/** Unregister a previously registered tab in the layer properties dialog */
virtual void unregisterMapLayerPropertiesFactory( QgsMapLayerPropertiesFactory* factory ) = 0;
// @todo is this deprecated in favour of QgsContextHelp?
/** Open a url in the users browser. By default the QGIS doc directory is used
* as the base for the URL. To open a URL that is not relative to the installed

View File

@ -1177,7 +1177,7 @@ void QgsMapCanvas::zoomToFeatureIds( QgsVectorLayer* layer, const QgsFeatureIds&
return;
}
QgsRectangle r = mapSettings().layerExtentToOutputExtent( layer, geom->boundingBox() );
rect.combineExtentWith( &r );
rect.combineExtentWith( r );
featureCount++;
}

View File

@ -0,0 +1,24 @@
/***************************************************************************
qgslayeroptionsfactory.cpp
--------------------------------------
Date : 9.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsmaplayerpropertiesfactory.h"
QgsMapLayerPropertiesFactory::QgsMapLayerPropertiesFactory()
{
}
QgsMapLayerPropertiesFactory::~QgsMapLayerPropertiesFactory()
{
}

View File

@ -0,0 +1,52 @@
/***************************************************************************
qgslayeroptionsfactory.h
--------------------------------------
Date : 9.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSLAYERPROPERTIESFACTORY_H
#define QGSLAYERPROPERTIESFACTORY_H
#include <QListWidgetItem>
#include "qgsvectorlayerpropertiespage.h"
/**
* @brief Factory class for creating custom map layer property pages
*/
class GUI_EXPORT QgsMapLayerPropertiesFactory
{
public:
/** Constructor */
QgsMapLayerPropertiesFactory();
/** Destructor */
virtual ~QgsMapLayerPropertiesFactory();
/**
* @brief Create a new properties page
* @param layer The layer for which to create the page
* @param parent The parent widget
* @return The new properties page instance
*/
virtual QgsVectorLayerPropertiesPage* createVectorLayerPropertiesPage( QgsVectorLayer* layer, QWidget* parent ) = 0;
/**
* @brief Creates the QListWidgetItem for the properties page
* @param layer The layer for which to create the item
* @param view The parent QListView
* @return The QListWidgetItem for the properties page
*/
virtual QListWidgetItem* createVectorLayerPropertiesItem( QgsVectorLayer* layer, QListWidget* view ) = 0;
};
#endif // QGSLAYERPROPERTIESFACTORY_H

View File

@ -558,7 +558,7 @@ void QgsRubberBand::updateRect()
}
else
{
r.combineExtentWith( &rect );
r.combineExtentWith( rect );
}
}
}

View File

@ -0,0 +1,22 @@
/***************************************************************************
qgsvectorlayerpropertiespage.cpp
--------------------------------------
Date : 8.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsvectorlayerpropertiespage.h"
QgsVectorLayerPropertiesPage::QgsVectorLayerPropertiesPage( QWidget *parent ) :
QWidget( parent )
{
}

View File

@ -0,0 +1,38 @@
/***************************************************************************
qgsvectorlayerpropertiespage.h
--------------------------------------
Date : 8.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSVECTORLAYERPROPERTIESPAGE_H
#define QGSVECTORLAYERPROPERTIESPAGE_H
#include <QWidget>
class QgsVectorLayer;
/**
* @brief Base class for custom vector layer property pages
*/
class GUI_EXPORT QgsVectorLayerPropertiesPage : public QWidget
{
Q_OBJECT
public:
/** Constructor */
explicit QgsVectorLayerPropertiesPage( QWidget *parent = 0 );
public slots:
/** Apply changes */
virtual void apply() = 0;
};
#endif // QGSVECTORLAYERPROPERTIESPAGE_H

View File

@ -1,102 +1,103 @@
# set path to additional CMake modules
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules ${CMAKE_MODULE_PATH})
IF (KEEP_GLOBE_CXX_FLAGS)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_OLD}")
ENDIF()
FIND_PACKAGE(OSG REQUIRED)
FIND_PACKAGE(OSGEARTH REQUIRED)
FIND_PACKAGE(Threads)
IF(QT5_BUILD)
FIND_PACKAGE(Qt5OpenGL REQUIRED)
ENDIF(QT5_BUILD)
IF(HAVE_OSGEARTH_CHILD_SPACING)
ADD_DEFINITIONS(-DHAVE_OSGEARTH_CHILD_SPACING)
ENDIF(HAVE_OSGEARTH_CHILD_SPACING)
IF(OSGEARTH_ELEVATION_QUERY)
ADD_DEFINITIONS(-DHAVE_OSGEARTH_ELEVATION_QUERY)
ENDIF(OSGEARTH_ELEVATION_QUERY)
########################################################
# Files
SET (globe_plugin_SRCS
globe_plugin.cpp
qgsosgearthtilesource.cpp
globe_plugin_dialog.cpp
)
IF (NOT HAVE_OSGEARTHQT)
SET(globe_plugin_SRCS
${globe_plugin_SRCS}
osgEarthQt/ViewerWidget.cpp
osgEarthUtil/Controls.cpp
)
ENDIF (NOT HAVE_OSGEARTHQT)
SET (globe_plugin_UIS
globe_plugin_dialog_guibase.ui
)
SET (globe_plugin_MOC_HDRS
globe_plugin.h
globe_plugin_dialog.h
SET (GLOBE_PLUGIN_SRCS
globe_plugin.cpp
qgsglobetilesource.cpp
qgsglobeplugindialog.cpp
qgsglobeinterface.cpp
qgsglobevectorlayerproperties.cpp
qgsglobefeatureidentify.cpp
qgsglobefrustumhighlight.cpp
qgsglobewidget.cpp
)
SET (globe_plugin_RCCS globe_plugin.qrc)
SET (GLOBE_PLUGIN_UIS
qgsglobeplugindialog.ui
qgsglobevectorlayerpropertiespage.ui
)
SET (GLOBE_PLUGIN_MOC_HDRS
globe_plugin.h
qgsglobeplugindialog.h
qgsglobeinterface.h
qgsglobevectorlayerproperties.h
qgsglobetilesource.h
qgsglobewidget.h
)
SET (GLOBE_PLUGIN_HDRS
qgsglobeinterface.h
qgsglobevectorlayerproperties.h
qgsglobefeatureidentify.h
qgsglobefrustumhighlight.h
)
SET (GLOBE_PLUGIN_RCCS globe_plugin.qrc)
########################################################
# Build
QT4_WRAP_UI (globe_plugin_UIS_H ${globe_plugin_UIS})
IF(WIN32)
ADD_DEFINITIONS("\"-DGLOBE_EXPORT=${DLLEXPORT}\"")
ELSE(WIN32)
ADD_DEFINITIONS("-DGLOBE_EXPORT=")
ENDIF(WIN32)
QT4_WRAP_CPP (globe_plugin_MOC_SRCS ${globe_plugin_MOC_HDRS})
QT4_WRAP_UI (GLOBE_PLUGIN_UIS_H ${GLOBE_PLUGIN_UIS})
QT4_ADD_RESOURCES(globe_plugin_RCC_SRCS ${globe_plugin_RCCS})
QT4_WRAP_CPP (GLOBE_PLUGIN_MOC_SRCS ${GLOBE_PLUGIN_MOC_HDRS})
ADD_LIBRARY (globeplugin MODULE ${globe_plugin_SRCS} ${globe_plugin_MOC_SRCS} ${globe_plugin_RCC_SRCS} ${globe_plugin_UIS_H})
QT4_ADD_RESOURCES(GLOBE_PLUGIN_RCC_SRCS ${GLOBE_PLUGIN_RCCS})
INCLUDE_DIRECTORIES(SYSTEM
${Qt5OpenGL_INCLUDE_DIRS}
${OSGEARTH_INCLUDE_DIR}
${OSG_INCLUDE_DIR}
${GEOS_INCLUDE_DIR}
)
ADD_LIBRARY (globeplugin SHARED ${GLOBE_PLUGIN_SRCS} ${GLOBE_PLUGIN_MOC_SRCS} ${GLOBE_PLUGIN_RCC_SRCS} ${GLOBE_PLUGIN_UIS_H} ${GLOBE_PLUGIN_HDRS})
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_BINARY_DIR}
../../core ../../core/geometry ../../core/raster
${OSGEARTH_INCLUDE_DIR}
${OSG_INCLUDE_DIR}
${GEOS_INCLUDE_DIR}
${SIP_INCLUDE_DIR}
../../core
../../core/geometry
../../core/raster
../../core/symbology-ng
../../gui
..
)
SET (OSGEARTH_LIBS
${OSGEARTH_LIBRARY}
${OSGEARTHFEATURES_LIBRARY}
${OSGEARTHUTIL_LIBRARY}
)
IF (HAVE_OSGEARTHQT)
SET(OSGEARTH_LIBS
${OSGEARTH_LIBS}
${OSGEARTHQT_LIBRARY}
)
ENDIF (HAVE_OSGEARTHQT)
TARGET_LINK_LIBRARIES(globeplugin
qgis_core
qgis_gui
${QT_QTOPENGL_LIBRARY}
${Qt5OpenGL_LIBRARIES}
${OSGDB_LIBRARY}
${OSGGA_LIBRARY}
${OSGUTIL_LIBRARY}
${OSG_LIBRARY}
${OSGQT_LIBRARY}
${OSGVIEWER_LIBRARY}
${OSGEARTH_LIBS}
${OSGEARTH_LIBRARY}
${OSGEARTHANNOTATION_LIBRARY}
${OSGEARTHFEATURES_LIBRARY}
${OSGEARTHUTIL_LIBRARY}
${OSGEARTHSYMBOLOGY_LIBRARY}
${OSGEARTHQT_LIBRARY}
${OPENTHREADS_LIBRARY}
)
IF (WITH_BINDINGS)
# Restore default CXX flags (without visibility=hidden, which breaks python bindings)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_OLD}")
ADD_SUBDIRECTORY(python)
ENDIF (WITH_BINDINGS)
ADD_SUBDIRECTORY(featuresource)
########################################################
# Install

View File

@ -0,0 +1,11 @@
# Required Vars:
# ${LIB_NAME}
# ${LIB_PUBLIC_HEADERS}
SET(INSTALL_INCDIR include)
# FIXME: Do not run for OS X framework
INSTALL(
FILES ${LIB_PUBLIC_HEADERS}
DESTINATION ${INSTALL_INCDIR}/osgEarthDrivers/${LIB_NAME}
)

View File

@ -0,0 +1,361 @@
#######################################################################################################
# macro to detect osg version and setup variables accordingly
#######################################################################################################
MACRO(DETECT_OSG_VERSION)
OPTION(APPEND_OPENSCENEGRAPH_VERSION "Append the OSG version number to the osgPlugins directory" ON)
# detect if osgversion can be found
FIND_PROGRAM(OSG_VERSION_EXE NAMES osgversion)
IF(OSG_VERSION_EXE AND NOT OPENSCENEGRAPH_MAJOR_VERSION AND NOT OPENSCENEGRAPH_MINOR_VERSION AND NOT OPENSCENEGRAPH_PATCH_VERSION)
#MESSAGE("OSGVERSION IS AT ${OSG_VERSION_EXE}")
# get parameters out of the osgversion
EXECUTE_PROCESS(COMMAND ${OSG_VERSION_EXE} --major-number OUTPUT_VARIABLE OPENSCENEGRAPH_MAJOR_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${OSG_VERSION_EXE} --minor-number OUTPUT_VARIABLE OPENSCENEGRAPH_MINOR_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${OSG_VERSION_EXE} --patch-number OUTPUT_VARIABLE OPENSCENEGRAPH_PATCH_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${OSG_VERSION_EXE} Matrix::value_type OUTPUT_VARIABLE OSG_USE_FLOAT_MATRIX OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${OSG_VERSION_EXE} Plane::value_type OUTPUT_VARIABLE OSG_USE_FLOAT_PLANE OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${OSG_VERSION_EXE} BoundingSphere::value_type OUTPUT_VARIABLE OSG_USE_FLOAT_BOUNDINGSPHERE OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(COMMAND ${OSG_VERSION_EXE} BoundingBox::value_type OUTPUT_VARIABLE OSG_USE_FLOAT_BOUNDINGBOX OUTPUT_STRIP_TRAILING_WHITESPACE)
# setup version numbers if we have osgversion
SET(OPENSCENEGRAPH_MAJOR_VERSION "${OPENSCENEGRAPH_MAJOR_VERSION}" CACHE STRING "OpenSceneGraph major version number")
SET(OPENSCENEGRAPH_MINOR_VERSION "${OPENSCENEGRAPH_MINOR_VERSION}" CACHE STRING "OpenSceneGraph minor version number")
SET(OPENSCENEGRAPH_PATCH_VERSION "${OPENSCENEGRAPH_PATCH_VERSION}" CACHE STRING "OpenSceneGraph patch version number")
SET(OPENSCENEGRAPH_SOVERSION "${OPENSCENEGRAPH_SOVERSION}" CACHE STRING "OpenSceneGraph so version number")
# just debug info
#MESSAGE(STATUS "Detected OpenSceneGraph v${OPENSCENEGRAPH_VERSION}.")
# setup float and double definitions
IF(OSG_USE_FLOAT_MATRIX MATCHES "float")
ADD_DEFINITIONS(-DOSG_USE_FLOAT_MATRIX)
ENDIF(OSG_USE_FLOAT_MATRIX MATCHES "float")
IF(OSG_USE_FLOAT_PLANE MATCHES "float")
ADD_DEFINITIONS(-DOSG_USE_FLOAT_PLANE)
ENDIF(OSG_USE_FLOAT_PLANE MATCHES "float")
IF(OSG_USE_FLOAT_BOUNDINGSPHERE MATCHES "double")
ADD_DEFINITIONS(-DOSG_USE_DOUBLE_BOUNDINGSPHERE)
ENDIF(OSG_USE_FLOAT_BOUNDINGSPHERE MATCHES "double")
IF(OSG_USE_FLOAT_BOUNDINGBOX MATCHES "double")
ADD_DEFINITIONS(-DOSG_USE_DOUBLE_BOUNDINGBOX)
ENDIF(OSG_USE_FLOAT_BOUNDINGBOX MATCHES "double")
ENDIF(OSG_VERSION_EXE AND NOT OPENSCENEGRAPH_MAJOR_VERSION AND NOT OPENSCENEGRAPH_MINOR_VERSION AND NOT OPENSCENEGRAPH_PATCH_VERSION)
#Initialize the version numbers to being empty. If they were set by osgversion, they will be left alone
SET(OPENSCENEGRAPH_MAJOR_VERSION "" CACHE STRING "OpenSceneGraph major version number")
SET(OPENSCENEGRAPH_MINOR_VERSION "" CACHE STRING "OpenSceneGraph minor version number")
SET(OPENSCENEGRAPH_PATCH_VERSION "" CACHE STRING "OpenSceneGraph patch version number")
SET(OPENSCENEGRAPH_SOVERSION "" CACHE STRING "OpenSceneGraph so version number")
if (OPENSCENEGRAPH_MAJOR_VERSION AND NOT OPENSCENEGRAPH_MINOR_VERSION STREQUAL "" AND NOT OPENSCENEGRAPH_PATCH_VERSION STREQUAL "")
SET(OPENSCENEGRAPH_VERSION ${OPENSCENEGRAPH_MAJOR_VERSION}.${OPENSCENEGRAPH_MINOR_VERSION}.${OPENSCENEGRAPH_PATCH_VERSION})
else (OPENSCENEGRAPH_MAJOR_VERSION AND NOT OPENSCENEGRAPH_MINOR_VERSION STREQUAL "" AND NOT OPENSCENEGRAPH_PATCH_VERSION STREQUAL "")
#MESSAGE("osgversion was found at ${OSG_VERSION_EXE} but failed to run")
SET(OPENSCENEGRAPH_VERSION)
endif (OPENSCENEGRAPH_MAJOR_VERSION AND NOT OPENSCENEGRAPH_MINOR_VERSION STREQUAL "" AND NOT OPENSCENEGRAPH_PATCH_VERSION STREQUAL "")
MARK_AS_ADVANCED(OPENSCENEGRAPH_VERSION)
IF (APPEND_OPENSCENEGRAPH_VERSION AND OPENSCENEGRAPH_VERSION)
SET(OSG_PLUGINS "osgPlugins-${OPENSCENEGRAPH_VERSION}" CACHE STRING "" FORCE)
MESSAGE(STATUS "Plugins will be installed under osgPlugins-${OPENSCENEGRAPH_VERSION} directory.")
else (APPEND_OPENSCENEGRAPH_VERSION AND OPENSCENEGRAPH_VERSION)
SET(OSG_PLUGINS CACHE STRING "" FORCE)
ENDIF(APPEND_OPENSCENEGRAPH_VERSION AND OPENSCENEGRAPH_VERSION)
MARK_AS_ADVANCED(OSG_PLUGINS)
#MESSAGE("OSG_PLUGINS=${OSG_PLUGINS}")
ENDMACRO(DETECT_OSG_VERSION)
#######################################################################################################
# macro for linking libraries that come from Findxxxx commands, so there is a variable that contains the
# full path of the library name. in order to differentiate release and debug, this macro get the
# NAME of the variables, so the macro gets as arguments the target name and the following list of parameters
# is intended as a list of variable names each one containing the path of the libraries to link to
# The existance of a variable name with _DEBUG appended is tested and, in case it' s value is used
# for linking to when in debug mode
# the content of this library for linking when in debugging
#######################################################################################################
MACRO(LINK_WITH_VARIABLES TRGTNAME)
FOREACH(varname ${ARGN})
IF(${varname}_DEBUG)
TARGET_LINK_LIBRARIES(${TRGTNAME} optimized "${${varname}}" debug "${${varname}_DEBUG}")
ELSE(${varname}_DEBUG)
TARGET_LINK_LIBRARIES(${TRGTNAME} "${${varname}}" )
ENDIF(${varname}_DEBUG)
ENDFOREACH(varname)
ENDMACRO(LINK_WITH_VARIABLES TRGTNAME)
MACRO(LINK_INTERNAL TRGTNAME)
IF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} GREATER 4)
TARGET_LINK_LIBRARIES(${TRGTNAME} ${ARGN})
ELSE(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} GREATER 4)
FOREACH(LINKLIB ${ARGN})
IF(MSVC AND OSG_MSVC_VERSIONED_DLL)
#when using versioned names, the .dll name differ from .lib name, there is a problem with that:
#CMake 2.4.7, at least seem to use PREFIX instead of IMPORT_PREFIX for computing linkage info to use into projects,
# so we full path name to specify linkage, this prevent automatic inferencing of dependencies, so we add explicit depemdencies
#to library targets used
TARGET_LINK_LIBRARIES(${TRGTNAME} optimized "${OUTPUT_LIBDIR}/${LINKLIB}${CMAKE_RELEASE_POSTFIX}.lib" debug "${OUTPUT_LIBDIR}/${LINKLIB}${CMAKE_DEBUG_POSTFIX}.lib")
ADD_DEPENDENCIES(${TRGTNAME} ${LINKLIB})
ELSE(MSVC AND OSG_MSVC_VERSIONED_DLL)
TARGET_LINK_LIBRARIES(${TRGTNAME} optimized "${LINKLIB}${CMAKE_RELEASE_POSTFIX}" debug "${LINKLIB}${CMAKE_DEBUG_POSTFIX}")
ENDIF(MSVC AND OSG_MSVC_VERSIONED_DLL)
ENDFOREACH(LINKLIB)
ENDIF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} GREATER 4)
ENDMACRO(LINK_INTERNAL TRGTNAME)
MACRO(LINK_EXTERNAL TRGTNAME)
FOREACH(LINKLIB ${ARGN})
TARGET_LINK_LIBRARIES(${TRGTNAME} "${LINKLIB}" )
ENDFOREACH(LINKLIB)
ENDMACRO(LINK_EXTERNAL TRGTNAME)
#######################################################################################################
# macro for common setup of core libraries: it links OPENGL_LIBRARIES in undifferentiated mode
#######################################################################################################
MACRO(LINK_CORELIB_DEFAULT CORELIB_NAME)
LINK_EXTERNAL(${CORELIB_NAME} ${OPENGL_LIBRARIES})
LINK_WITH_VARIABLES(${CORELIB_NAME} OPENTHREADS_LIBRARY)
IF(OSGEARTH_SONAMES)
SET_TARGET_PROPERTIES(${CORELIB_NAME} PROPERTIES VERSION ${OSGEARTH_VERSION} SOVERSION ${OSGEARTH_SOVERSION})
ENDIF(OSGEARTH_SONAMES)
ENDMACRO(LINK_CORELIB_DEFAULT CORELIB_NAME)
#######################################################################################################
# macro for common setup of plugins, examples and applications it expect some variables to be set:
# either within the local CMakeLists or higher in hierarchy
# TARGET_NAME is the name of the folder and of the actually .exe or .so or .dll
# TARGET_TARGETNAME is the name of the target , this get buit out of a prefix, if present and TARGET_TARGETNAME
# TARGET_SRC are the sources of the target
# TARGET_H are the eventual headers of the target
# TARGET_LIBRARIES are the libraries to link to that are internal to the project and have d suffix for debug
# TARGET_EXTERNAL_LIBRARIES are external libraries and are not differentiated with d suffix
# TARGET_LABEL is the label IDE should show up for targets
##########################################################################################################
MACRO(SETUP_LINK_LIBRARIES)
######################################################################
#
# This set up the libraries to link to, it assumes there are two variable: one common for a group of examples or plagins
# kept in the variable TARGET_COMMON_LIBRARIES and an example or plugin specific kept in TARGET_ADDED_LIBRARIES
# they are combined in a single list checked for unicity
# the suffix ${CMAKE_DEBUG_POSTFIX} is used for differentiating optimized and debug
#
# a second variable TARGET_EXTERNAL_LIBRARIES hold the list of libraries not differentiated between debug and optimized
##################################################################################
SET(TARGET_LIBRARIES ${TARGET_COMMON_LIBRARIES})
FOREACH(LINKLIB ${TARGET_ADDED_LIBRARIES})
SET(TO_INSERT TRUE)
FOREACH (value ${TARGET_COMMON_LIBRARIES})
IF (${value} STREQUAL ${LINKLIB})
SET(TO_INSERT FALSE)
ENDIF (${value} STREQUAL ${LINKLIB})
ENDFOREACH (value ${TARGET_COMMON_LIBRARIES})
IF(TO_INSERT)
LIST(APPEND TARGET_LIBRARIES ${LINKLIB})
ENDIF(TO_INSERT)
ENDFOREACH(LINKLIB)
# FOREACH(LINKLIB ${TARGET_LIBRARIES})
# TARGET_LINK_LIBRARIES(${TARGET_TARGETNAME} optimized ${LINKLIB} debug "${LINKLIB}${CMAKE_DEBUG_POSTFIX}")
# ENDFOREACH(LINKLIB)
LINK_INTERNAL(${TARGET_TARGETNAME} ${TARGET_LIBRARIES})
FOREACH(LINKLIB ${TARGET_EXTERNAL_LIBRARIES})
TARGET_LINK_LIBRARIES(${TARGET_TARGETNAME} ${LINKLIB})
ENDFOREACH(LINKLIB)
IF(TARGET_LIBRARIES_VARS)
LINK_WITH_VARIABLES(${TARGET_TARGETNAME} ${TARGET_LIBRARIES_VARS})
ENDIF(TARGET_LIBRARIES_VARS)
ENDMACRO(SETUP_LINK_LIBRARIES)
############################################################################################
# this is the common set of command for all the plugins
MACRO(SETUP_PLUGIN PLUGIN_NAME)
SET(TARGET_NAME ${PLUGIN_NAME} )
#MESSAGE("in -->SETUP_PLUGIN<-- ${TARGET_NAME}-->${TARGET_SRC} <--> ${TARGET_H}<--")
SOURCE_GROUP( "Header Files" FILES ${TARGET_H} )
## we have set up the target label and targetname by taking into account global prfix (osgdb_)
IF(NOT TARGET_TARGETNAME)
SET(TARGET_TARGETNAME "${TARGET_DEFAULT_PREFIX}${TARGET_NAME}")
ENDIF(NOT TARGET_TARGETNAME)
IF(NOT TARGET_LABEL)
SET(TARGET_LABEL "${TARGET_DEFAULT_LABEL_PREFIX} ${TARGET_NAME}")
ENDIF(NOT TARGET_LABEL)
# here we use the command to generate the library
IF (DYNAMIC_OSGEARTH)
ADD_LIBRARY(${TARGET_TARGETNAME} MODULE ${TARGET_SRC} ${TARGET_H})
ELSE (DYNAMIC_OSGEARTH)
ADD_LIBRARY(${TARGET_TARGETNAME} STATIC ${TARGET_SRC} ${TARGET_H})
ENDIF(DYNAMIC_OSGEARTH)
#not sure if needed, but for plugins only msvc need the d suffix
IF(NOT MSVC)
IF(NOT UNIX)
SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES DEBUG_POSTFIX "")
ENDIF(NOT UNIX)
ENDIF(NOT MSVC)
SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PROJECT_LABEL "${TARGET_LABEL}")
SETUP_LINK_LIBRARIES()
#the installation path are differentiated for win32 that install in bib versus other architecture that install in lib${LIB_POSTFIX}/${VPB_PLUGINS}
IF(WIN32)
INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib/${OSG_PLUGINS} LIBRARY DESTINATION bin/${OSG_PLUGINS} )
#Install to the OSG_DIR as well
IF(OSGEARTH_INSTALL_TO_OSG_DIR AND OSG_DIR)
INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION ${OSG_DIR}/bin/${OSG_PLUGINS} LIBRARY DESTINATION ${OSG_DIR}/bin/${OSG_PLUGINS} )
ENDIF(OSGEARTH_INSTALL_TO_OSG_DIR AND OSG_DIR)
ELSE(WIN32)
INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib${LIB_POSTFIX}/${OSG_PLUGINS} LIBRARY DESTINATION lib${LIB_POSTFIX}/${OSG_PLUGINS} )
#Install to the OSG_DIR as well
IF(OSGEARTH_INSTALL_TO_OSG_DIR AND OSG_DIR)
INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION ${OSG_DIR}/bin LIBRARY DESTINATION lib${LIB_POSTFIX}/bin)
ENDIF(OSGEARTH_INSTALL_TO_OSG_DIR AND OSG_DIR)
ENDIF(WIN32)
#finally, set up the solution folder -gw
SET_PROPERTY(TARGET ${TARGET_TARGETNAME} PROPERTY FOLDER "Plugins")
ENDMACRO(SETUP_PLUGIN)
#################################################################################################################
# this is the macro for example and application setup
###########################################################
MACRO(SETUP_EXE IS_COMMANDLINE_APP)
#MESSAGE("in -->SETUP_EXE<-- ${TARGET_NAME}-->${TARGET_SRC} <--> ${TARGET_H}<--")
IF(NOT TARGET_TARGETNAME)
SET(TARGET_TARGETNAME "${TARGET_DEFAULT_PREFIX}${TARGET_NAME}")
ENDIF(NOT TARGET_TARGETNAME)
IF(NOT TARGET_LABEL)
SET(TARGET_LABEL "${TARGET_DEFAULT_LABEL_PREFIX} ${TARGET_NAME}")
ENDIF(NOT TARGET_LABEL)
IF(${IS_COMMANDLINE_APP})
ADD_EXECUTABLE(${TARGET_TARGETNAME} ${TARGET_SRC} ${TARGET_H})
ELSE(${IS_COMMANDLINE_APP})
IF(APPLE)
# SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${VIRTUALPLANETBUILDER_MAJOR_VERSION}.${VIRTUALPLANETBUILDER_MINOR_VERSION}.${VIRTUALPLANETBUILDER_PATCH_VERSION}")
# Short Version is the "marketing version". It is the version
# the user sees in an information panel.
SET(MACOSX_BUNDLE_SHORT_VERSION_STRING "${OSGEARTH_MAJOR_VERSION}.${OSGEARTH_MINOR_VERSION}.${OSGEARTH_PATCH_VERSION}")
# Bundle version is the version the OS looks at.
SET(MACOSX_BUNDLE_BUNDLE_VERSION "${OSGEARTH_MAJOR_VERSION}.${OSGEARTH_MINOR_VERSION}.${OSGEARTH__PATCH_VERSION}")
SET(MACOSX_BUNDLE_GUI_IDENTIFIER "org.osgearth.${TARGET_TARGETNAME}" )
SET(MACOSX_BUNDLE_BUNDLE_NAME "${TARGET_NAME}" )
# SET(MACOSX_BUNDLE_ICON_FILE "myicon.icns")
# SET(MACOSX_BUNDLE_COPYRIGHT "")
# SET(MACOSX_BUNDLE_INFO_STRING "Info string, localized?")
ENDIF(APPLE)
IF(WIN32)
IF (REQUIRE_WINMAIN_FLAG)
SET(PLATFORM_SPECIFIC_CONTROL WIN32)
ENDIF(REQUIRE_WINMAIN_FLAG)
ENDIF(WIN32)
IF(APPLE)
IF(VPB_BUILD_APPLICATION_BUNDLES)
SET(PLATFORM_SPECIFIC_CONTROL MACOSX_BUNDLE)
ENDIF(VPB_BUILD_APPLICATION_BUNDLES)
ENDIF(APPLE)
ADD_EXECUTABLE(${TARGET_TARGETNAME} ${PLATFORM_SPECIFIC_CONTROL} ${TARGET_SRC} ${TARGET_H})
ENDIF(${IS_COMMANDLINE_APP})
SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES PROJECT_LABEL "${TARGET_LABEL}")
SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES OUTPUT_NAME ${TARGET_NAME})
SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES DEBUG_OUTPUT_NAME "${TARGET_NAME}${CMAKE_DEBUG_POSTFIX}")
SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES RELEASE_OUTPUT_NAME "${TARGET_NAME}${CMAKE_RELEASE_POSTFIX}")
SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES RELWITHDEBINFO_OUTPUT_NAME "${TARGET_NAME}${CMAKE_RELWITHDEBINFO_POSTFIX}")
SET_TARGET_PROPERTIES(${TARGET_TARGETNAME} PROPERTIES MINSIZEREL_OUTPUT_NAME "${TARGET_NAME}${CMAKE_MINSIZEREL_POSTFIX}")
SETUP_LINK_LIBRARIES()
ENDMACRO(SETUP_EXE)
# Takes optional second argument (is_commandline_app?) in ARGV1
MACRO(SETUP_APPLICATION APPLICATION_NAME)
SET(TARGET_NAME ${APPLICATION_NAME} )
IF(${ARGC} GREATER 1)
SET(IS_COMMANDLINE_APP ${ARGV1})
ELSE(${ARGC} GREATER 1)
SET(IS_COMMANDLINE_APP 0)
ENDIF(${ARGC} GREATER 1)
SETUP_EXE(${IS_COMMANDLINE_APP})
INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION bin )
#Install to the OSG_DIR as well
IF(OSGEARTH_INSTALL_TO_OSG_DIR AND OSG_DIR)
INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION ${OSG_DIR}/bin)
ENDIF(OSGEARTH_INSTALL_TO_OSG_DIR AND OSG_DIR)
SET_PROPERTY(TARGET ${TARGET_TARGETNAME} PROPERTY FOLDER "Samples")
ENDMACRO(SETUP_APPLICATION)
MACRO(SETUP_COMMANDLINE_APPLICATION APPLICATION_NAME)
SETUP_APPLICATION(${APPLICATION_NAME} 1)
ENDMACRO(SETUP_COMMANDLINE_APPLICATION)
# Takes optional second argument (is_commandline_app?) in ARGV1
MACRO(SETUP_EXAMPLE EXAMPLE_NAME)
SET(TARGET_NAME ${EXAMPLE_NAME} )
IF(${ARGC} GREATER 1)
SET(IS_COMMANDLINE_APP ${ARGV1})
ELSE(${ARGC} GREATER 1)
SET(IS_COMMANDLINE_APP 0)
ENDIF(${ARGC} GREATER 1)
SETUP_EXE(${IS_COMMANDLINE_APP})
INSTALL(TARGETS ${TARGET_TARGETNAME} RUNTIME DESTINATION share/OpenSceneGraph/bin )
ENDMACRO(SETUP_EXAMPLE)
MACRO(SETUP_COMMANDLINE_EXAMPLE EXAMPLE_NAME)
SETUP_EXAMPLE(${EXAMPLE_NAME} 1)
ENDMACRO(SETUP_COMMANDLINE_EXAMPLE)

View File

@ -0,0 +1,50 @@
###################################################
# osgEarth plugin
###################################################
SET(OSGEARTH_PLUGIN_PREFIX "")
SET(LIB_POSTFIX ${LIB_SUFFIX})
SET(DYNAMIC_OSGEARTH "ON" )
SET(OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC "SHARED")
# SET(CMAKE_SHARED_MODULE_PREFIX ${OSGEARTH_PLUGIN_PREFIX})
SET(TARGET_DEFAULT_PREFIX "osgdb_")
SET(TARGET_DEFAULT_LABEL_PREFIX "Plugin")
INCLUDE( OsgEarthMacroUtils )
SET(TARGET_SRC
qgsglobefeaturesource.cpp
)
SET (TARGET_MOC_HDRS
qgsglobefeaturesource.h
)
SET(TARGET_HDRS
qgsglobefeaturecursor.h
qgsglobefeatureoptions.h
qgsglobefeatureutils.h
)
QT4_WRAP_CPP(TARGET_MOC_SRCS ${TARGET_MOC_HDRS})
SET(TARGET_SRC ${TARGET_SRC} ${TARGET_MOC_SRCS})
SET(TARGET_COMMON_LIBRARIES ${TARGET_COMMON_LIBRARIES}
qgis_core
qgis_gui
${OSGDB_LIBRARY}
${OSG_LIBRARY}
${OSGEARTH_LIBRARY}
${OSGEARTHFEATURES_LIBRARY}
${OSGEARTHSYMBOLOGY_LIBRARY}
${OSGEARTHUTIL_LIBRARY}
${OPENTHREADS_LIBRARY}
)
SETUP_PLUGIN(osgearth_feature_qgis)
# to install public driver includes:
SET(LIB_NAME feature_qgis)
SET(LIB_PUBLIC_HEADERS ${TARGET_HDRS} ${TARGET_MOC_HDRS})
INCLUDE(ModuleInstallOsgEarthDriverIncludes OPTIONAL)

View File

@ -0,0 +1,66 @@
/***************************************************************************
qgsglobefeaturecursor.h
--------------------------------------
Date : 11.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGLOBEFEATURECURSOR_H
#define QGSGLOBEFEATURECURSOR_H
#include <osgEarthFeatures/FeatureCursor>
#include <qgsfeature.h>
#include <qgsfeatureiterator.h>
#include <qgsvectorlayer.h>
#include "qgsglobefeatureutils.h"
class QgsGlobeFeatureCursor : public osgEarth::Features::FeatureCursor
{
public:
QgsGlobeFeatureCursor( QgsVectorLayer* layer, const QgsFeatureIterator& iterator )
: mIterator( iterator )
, mLayer( layer )
{
mIterator.nextFeature( mFeature );
}
bool hasMore() const override
{
return mFeature.isValid();
}
osgEarth::Features::Feature* nextFeature() override
{
if ( mFeature.isValid() )
{
osgEarth::Features::Feature *feat = QgsGlobeFeatureUtils::featureFromQgsFeature( mLayer, mFeature );
mIterator.nextFeature( mFeature );
return feat;
}
else
{
QgsDebugMsg( "WARNING: Returning NULL feature to osgEarth" );
return NULL;
}
}
private:
QgsFeatureIterator mIterator;
QgsVectorLayer* mLayer;
// Cached feature which will be returned next.
// Always contains the next feature which will be returned
// (Because hasMore() needs to know if we are able to return a next feature)
QgsFeature mFeature;
};
#endif // QGSGLOBEFEATURECURSOR_H

View File

@ -0,0 +1,81 @@
/* -*-c++-*- */
/*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef QGSGLOBEFEATUREOPTIONS_H
#define QGSGLOBEFEATUREOPTIONS_H
#include <osgEarth/Common>
#include <osgEarthFeatures/FeatureSource>
class QgsVectorLayer;
class QgsGlobeFeatureOptions : public osgEarth::Features::FeatureSourceOptions // NO EXPORT; header only
{
private:
template <class T>
class RefPtr : public osg::Referenced
{
public:
RefPtr( T* ptr ) : mPtr( ptr ) {}
T* ptr() { return mPtr; }
private:
T* mPtr;
};
public:
QgsGlobeFeatureOptions( const ConfigOptions& opt = ConfigOptions() )
: osgEarth::Features::FeatureSourceOptions( opt )
{
// Call the driver declared as "osgearth_feature_qgis"
setDriver( "qgis" );
fromConfig( _conf );
}
osgEarth::Config getConfig() const override
{
osgEarth::Config conf = osgEarth::Features::FeatureSourceOptions::getConfig();
conf.updateIfSet( "layerId", mLayerId );
conf.updateNonSerializable( "layer", new RefPtr< QgsVectorLayer >( mLayer ) );
return conf;
}
osgEarth::optional<std::string>& layerId() { return mLayerId; }
const osgEarth::optional<std::string>& layerId() const { return mLayerId; }
QgsVectorLayer* layer() const { return mLayer; }
void setLayer( QgsVectorLayer* layer ) { mLayer = layer; }
protected:
void mergeConfig( const osgEarth::Config& conf ) override
{
osgEarth::Features::FeatureSourceOptions::mergeConfig( conf );
fromConfig( conf );
}
private:
void fromConfig( const osgEarth::Config& conf )
{
conf.getIfSet( "layerId", mLayerId );
RefPtr< QgsVectorLayer > *layer_ptr = conf.getNonSerializable< RefPtr< QgsVectorLayer > >( "layer" );
mLayer = layer_ptr ? layer_ptr->ptr() : 0;
}
osgEarth::optional<std::string> mLayerId;
QgsVectorLayer* mLayer;
};
#endif // QGSGLOBEFEATUREOPTIONS_H

View File

@ -0,0 +1,145 @@
#include <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <qgsfeature.h>
#include <qgsfeatureiterator.h>
#include <qgsgeometry.h>
#include <qgslogger.h>
#include <qgsrectangle.h>
#include "qgsvectorlayer.h"
#include "qgsglobefeaturecursor.h"
#include "qgsglobefeatureutils.h"
#include "qgsglobefeaturesource.h"
QgsGlobeFeatureSource::QgsGlobeFeatureSource( const QgsGlobeFeatureOptions& options ) :
mOptions( options ),
mLayer( 0 ),
mProfile( 0 )
{
}
void QgsGlobeFeatureSource::initialize( const osgDB::Options* dbOptions )
{
Q_UNUSED( dbOptions )
mLayer = mOptions.layer();
connect( mLayer, SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ), this, SLOT( attributeValueChanged( QgsFeatureId, int, QVariant ) ) );
connect( mLayer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SLOT( geometryChanged( QgsFeatureId, QgsGeometry& ) ) );
// create the profile
osgEarth::SpatialReference* ref = osgEarth::SpatialReference::create( mLayer->crs().toWkt().toStdString() );
if ( 0 == ref )
{
std::cout << "Cannot find the spatial reference" << std::endl;
return;
}
QgsRectangle ext = mLayer->extent();
osgEarth::GeoExtent geoext( ref, ext.xMinimum(), ext.yMinimum(), ext.xMaximum(), ext.yMaximum() );
mProfile = new osgEarth::Features::FeatureProfile( geoext );
mSchema = QgsGlobeFeatureUtils::schemaForFields( mLayer->pendingFields() );
}
osgEarth::Features::FeatureCursor* QgsGlobeFeatureSource::createFeatureCursor( const osgEarth::Symbology::Query& query )
{
QgsFeatureRequest request;
if ( query.expression().isSet() )
{
QgsDebugMsg( QString( "Ignoring query expression '%1'" ). arg( query.expression().value().c_str() ) );
}
if ( query.bounds().isSet() )
{
QgsRectangle bounds( query.bounds()->xMin(), query.bounds()->yMin(), query.bounds()->xMax(), query.bounds()->yMax() );
request.setFilterRect( bounds );
}
QgsFeatureIterator it = mLayer->getFeatures( request );
return new QgsGlobeFeatureCursor( mLayer, it );
}
osgEarth::Features::Feature* QgsGlobeFeatureSource::getFeature( osgEarth::Features::FeatureID fid )
{
QgsFeature feat;
mLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( feat );
osgEarth::Features::Feature* feature = QgsGlobeFeatureUtils::featureFromQgsFeature( mLayer, feat );
FeatureMap_t::iterator it = mFeatures.find( fid );
if ( it == mFeatures.end() )
{
mFeatures.insert( std::make_pair( fid, osg::observer_ptr<osgEarth::Features::Feature>( feature ) ) );
}
else
{
it->second = osg::observer_ptr<osgEarth::Features::Feature>( feature );
}
return feature;
}
osgEarth::Features::Geometry::Type QgsGlobeFeatureSource::getGeometryType() const
{
switch ( mLayer->geometryType() )
{
case QGis::Point:
return osgEarth::Features::Geometry::TYPE_POINTSET;
case QGis::Line:
return osgEarth::Features::Geometry::TYPE_LINESTRING;
case QGis::Polygon:
return osgEarth::Features::Geometry::TYPE_POLYGON;
default:
return osgEarth::Features::Geometry::TYPE_UNKNOWN;
}
return osgEarth::Features::Geometry::TYPE_UNKNOWN;
}
int QgsGlobeFeatureSource::getFeatureCount() const
{
return mLayer->featureCount();
}
void QgsGlobeFeatureSource::attributeValueChanged( const QgsFeatureId& featureId, int idx, const QVariant& value )
{
FeatureMap_t::iterator it = mFeatures.find( featureId );
if ( it != mFeatures.end() )
{
osgEarth::Features::Feature* feature = it->second.get();
QgsGlobeFeatureUtils::setFeatureField( feature, mLayer->pendingFields().at( idx ), value );
}
}
void QgsGlobeFeatureSource::geometryChanged( const QgsFeatureId& featureId, QgsGeometry& geometry )
{
FeatureMap_t::iterator it = mFeatures.find( featureId );
if ( it != mFeatures.end() )
{
osgEarth::Features::Feature* feature = it->second.get();
feature->setGeometry( QgsGlobeFeatureUtils::geometryFromQgsGeometry( geometry ) );
}
}
class QgsGlobeFeatureSourceFactory : public osgEarth::Features::FeatureSourceDriver
{
public:
QgsGlobeFeatureSourceFactory()
{
supportsExtension( "osgearth_feature_qgis", "QGIS feature driver for osgEarth" );
}
virtual osgDB::ReaderWriter::ReadResult readObject( const std::string& file_name, const osgDB::Options* options ) const override
{
// this function seems to be called for every plugin
// we declare supporting the special extension "osgearth_feature_qgis"
if ( !acceptsExtension( osgDB::getLowerCaseFileExtension( file_name ) ) )
return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
return osgDB::ReaderWriter::ReadResult( new QgsGlobeFeatureSource( getFeatureSourceOptions( options ) ) );
}
};
REGISTER_OSGPLUGIN( osgearth_feature_qgis, QgsGlobeFeatureSourceFactory )

View File

@ -0,0 +1,48 @@
#ifndef QGSGLOBEFEATURESOURCE_H
#define QGSGLOBEFEATURESOURCE_H
#include <osgEarthFeatures/FeatureSource>
#include <QObject>
#include "qgsglobefeatureoptions.h"
#include "qgsfeature.h"
class QgsGlobeFeatureSource : public QObject, public osgEarth::Features::FeatureSource
{
Q_OBJECT
public:
QgsGlobeFeatureSource( const QgsGlobeFeatureOptions& options = osgEarth::Features::ConfigOptions() );
osgEarth::Features::FeatureCursor* createFeatureCursor( const osgEarth::Symbology::Query& query = osgEarth::Symbology::Query() ) override;
int getFeatureCount() const override;
osgEarth::Features::Feature* getFeature( osgEarth::Features::FeatureID fid ) override;
osgEarth::Features::Geometry::Type getGeometryType() const override;
QgsVectorLayer* layer() const { return mLayer; }
const char* className() const override { return "QGISFeatureSource"; }
const char* libraryName() const override { return "QGIS"; }
void initialize( const osgDB::Options* dbOptions );
protected:
const osgEarth::Features::FeatureProfile* createFeatureProfile() override { return mProfile; }
const osgEarth::Features::FeatureSchema& getSchema() const override { return mSchema; }
~QgsGlobeFeatureSource() {}
private:
QgsGlobeFeatureOptions mOptions;
QgsVectorLayer* mLayer;
osgEarth::Features::FeatureProfile* mProfile;
osgEarth::Features::FeatureSchema mSchema;
typedef std::map<osgEarth::Features::FeatureID, osg::observer_ptr<osgEarth::Features::Feature> > FeatureMap_t;
FeatureMap_t mFeatures;
private slots:
void attributeValueChanged( const QgsFeatureId&featureId, int idx, const QVariant &value );
void geometryChanged( const QgsFeatureId&featureId, QgsGeometry&geometry );
};
#endif // QGSGLOBEFEATURESOURCE_H

View File

@ -0,0 +1,254 @@
/***************************************************************************
qgsglobefeatureutils.h
--------------------------------------
Date : 11.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGLOBEFEATUREUTILS_H
#define QGSGLOBEFEATUREUTILS_H
#include <osgEarthFeatures/Feature>
#include <osg/ValueObject>
#include <qgsfield.h>
#include <qgsgeometry.h>
#include <qgsmultipointv2.h>
#include <qgsmultilinestringv2.h>
#include <qgsmultipolygonv2.h>
#include <qgspolygonv2.h>
#include <qgslinestringv2.h>
#include <qgsvectorlayer.h>
class QgsGlobeFeatureUtils
{
public:
static inline QgsPointV2 qgsPointFromPoint( const osg::Vec3d& pt )
{
return QgsPointV2( QgsWKBTypes::PointZ, pt.x(), pt.y(), pt.z() );
}
static inline osg::Vec3d pointFromQgsPoint( const QgsPointV2& pt )
{
return osg::Vec3d( pt.x(), pt.y(), pt.z() );
}
static inline osgEarth::Features::LineString* lineStringFromQgsLineString( const QgsLineStringV2* lineString )
{
QgsLineStringV2* linearString = lineString->curveToLine();
osgEarth::Features::LineString* retLineString = new osgEarth::Features::LineString();
for ( int iVtx = 0, nVtx = linearString->vertexCount(); iVtx < nVtx; ++iVtx )
{
retLineString->push_back( pointFromQgsPoint( linearString->vertexAt( QgsVertexId( 0, 0, iVtx ) ) ) );
}
delete linearString;
return retLineString;
}
static inline osgEarth::Features::Polygon* polygonFromQgsPolygon( const QgsPolygonV2* polygon )
{
QgsPolygonV2* linearPolygon = polygon->toPolygon();
// a ring for osg earth is open (first point != last point)
// an outer ring is oriented CCW, an inner ring is oriented CW
osgEarth::Features::Polygon* retPoly = new osgEarth::Features::Polygon();
// the outer ring
for ( int iVtx = 0, nVtx = linearPolygon->vertexCount( 0, 0 ); iVtx < nVtx; ++iVtx )
{
retPoly->push_back( pointFromQgsPoint( linearPolygon->vertexAt( QgsVertexId( 0, 0, iVtx ) ) ) );
}
retPoly->rewind( osgEarth::Symbology::Ring::ORIENTATION_CCW );
for ( int iRing = 1, nRings = linearPolygon->ringCount( 0 ); iRing < nRings; ++iRing )
{
osgEarth::Features::Ring* innerRing = new osgEarth::Features::Ring();
for ( int iVtx = 0, nVtx = linearPolygon->vertexCount( 0, iRing ); iVtx < nVtx; ++iVtx )
{
innerRing->push_back( pointFromQgsPoint( linearPolygon->vertexAt( QgsVertexId( 0, iRing, iVtx ) ) ) );
}
innerRing->rewind( osgEarth::Symbology::Ring::ORIENTATION_CW );
retPoly->getHoles().push_back( osg::ref_ptr<osgEarth::Features::Ring>( innerRing ) );
}
delete linearPolygon;
return retPoly;
}
static inline osgEarth::Features::Geometry* geometryFromQgsGeometry( const QgsGeometry& geom )
{
#if 0
// test srid
std::cout << "geom = " << &geom << std::endl;
std::cout << "wkb = " << geom.asWkb() << std::endl;
uint32_t srid;
memcpy( &srid, geom.asWkb() + 2 + sizeof( void* ), sizeof( uint32_t ) );
std::cout << "srid = " << srid << std::endl;
#endif
switch ( QgsWKBTypes::flatType( geom.geometry()->wkbType() ) )
{
case QgsWKBTypes::Point:
{
osgEarth::Features::PointSet* pointSet = new osgEarth::Features::PointSet();
pointSet->push_back( pointFromQgsPoint( *static_cast<QgsPointV2*>( geom.geometry() ) ) );
return pointSet;
}
case QGis::WKBMultiPoint:
{
osgEarth::Features::PointSet* pointSet = new osgEarth::Features::PointSet();
QgsMultiPointV2* multiPoint = static_cast<QgsMultiPointV2*>( geom.geometry() );
for ( int i = 0, n = multiPoint->numGeometries(); i < n; ++i )
{
pointSet->push_back( pointFromQgsPoint( *static_cast<QgsPointV2*>( multiPoint->geometryN( i ) ) ) );
}
return pointSet;
}
case QgsWKBTypes::LineString:
case QgsWKBTypes::CircularString:
case QgsWKBTypes::CompoundCurve:
{
return lineStringFromQgsLineString( static_cast<QgsLineStringV2*>( geom.geometry() ) );
}
case QgsWKBTypes::MultiLineString:
{
osgEarth::Features::MultiGeometry* multiGeometry = new osgEarth::Features::MultiGeometry();
QgsMultiLineStringV2* multiLineString = static_cast<QgsMultiLineStringV2*>( geom.geometry() );
for ( int i = 0, n = multiLineString->numGeometries(); i < n; ++i )
{
multiGeometry->getComponents().push_back( lineStringFromQgsLineString( static_cast<QgsLineStringV2*>( multiLineString->geometryN( i ) ) ) );
}
return multiGeometry;
}
case QgsWKBTypes::Polygon:
case QgsWKBTypes::CurvePolygon:
{
return polygonFromQgsPolygon( static_cast<QgsPolygonV2*>( geom.geometry() ) );
}
case QgsWKBTypes::MultiPolygon:
{
osgEarth::Features::MultiGeometry* multiGeometry = new osgEarth::Features::MultiGeometry();
QgsMultiPolygonV2* multiPolygon = static_cast<QgsMultiPolygonV2*>( geom.geometry() );
for ( int i = 0, n = multiPolygon->numGeometries(); i < n; ++i )
{
multiGeometry->getComponents().push_back( polygonFromQgsPolygon( static_cast<QgsPolygonV2*>( multiPolygon->geometryN( i ) ) ) );
}
return multiGeometry;
}
default:
break;
}
return 0;
}
static osgEarth::Features::Feature* featureFromQgsFeature( QgsVectorLayer* layer, QgsFeature& feat )
{
osgEarth::Features::Geometry* nGeom = geometryFromQgsGeometry( *feat.geometry() );
osgEarth::Features::Feature* retFeat = new osgEarth::Features::Feature( nGeom, 0, osgEarth::Style(), feat.id() );
const QgsFields& fields = layer->pendingFields();
const QgsAttributes& attrs = feat.attributes();
for ( int idx = 0, numFlds = fields.size(); idx < numFlds; ++idx )
{
setFeatureField( retFeat, fields.at( idx ), attrs[idx] );
}
retFeat->setUserValue( "qgisLayerId", layer->id().toStdString() );
return retFeat;
}
static void setFeatureField( osgEarth::Features::Feature* feature, const QgsField& field, const QVariant& value )
{
std::string name = field.name().toStdString();
switch ( field.type() )
{
case QVariant::Bool:
if ( !value.isNull() )
feature->set( name, value.toBool() );
else
feature->setNull( name, osgEarth::Features::ATTRTYPE_BOOL );
break;
case QVariant::Int:
case QVariant::UInt:
case QVariant::LongLong:
case QVariant::ULongLong:
if ( !value.isNull() )
feature->set( name, value.toInt() );
else
feature->setNull( name, osgEarth::Features::ATTRTYPE_INT );
break;
case QVariant::Double:
if ( !value.isNull() )
feature->set( name, value.toDouble() );
else
feature->setNull( name, osgEarth::Features::ATTRTYPE_DOUBLE );
break;
case QVariant::Char:
case QVariant::String:
default:
if ( !value.isNull() )
feature->set( name, value.toString().toStdString() );
else
feature->setNull( name, osgEarth::Features::ATTRTYPE_STRING );
break;
}
}
static osgEarth::Features::FeatureSchema schemaForFields( const QgsFields& fields )
{
osgEarth::Features::FeatureSchema schema;
for ( int idx = 0, numFlds = fields.size(); idx < numFlds; ++idx )
{
const QgsField& fld = fields.at( idx );
std::string name = fld.name().toStdString();
switch ( fld.type() )
{
case QVariant::Bool:
schema.insert( std::make_pair( name, osgEarth::Features::ATTRTYPE_BOOL ) );
break;
case QVariant::Int:
case QVariant::UInt:
case QVariant::LongLong:
case QVariant::ULongLong:
schema.insert( std::make_pair( name, osgEarth::Features::ATTRTYPE_INT ) );
break;
case QVariant::Double:
schema.insert( std::make_pair( name, osgEarth::Features::ATTRTYPE_DOUBLE ) );
break;
case QVariant::Char:
case QVariant::String:
default:
schema.insert( std::make_pair( name, osgEarth::Features::ATTRTYPE_STRING ) );
break;
}
}
return schema;
}
};
#endif // QGSGLOBEFEATUREUTILS_H

File diff suppressed because it is too large Load Diff

View File

@ -19,171 +19,165 @@
#ifndef QGS_GLOBE_PLUGIN_H
#define QGS_GLOBE_PLUGIN_H
#include "qgsconfig.h"
#include "qgisplugin.h"
#include "qgsosgearthtilesource.h"
#include "globe_plugin_dialog.h"
#include <qgisplugin.h>
#include <QObject>
#include <osgViewer/Viewer>
#include <osgEarth/MapNode>
#include <osgEarth/ImageLayer>
#include <osgEarthUtil/EarthManipulator>
#ifndef HAVE_OSGEARTHQT //use backported controls if osgEarth <= 2.1
#define USE_BACKPORTED_CONTROLS
#endif
#ifdef USE_BACKPORTED_CONTROLS
#include "osgEarthUtil/Controls"
using namespace osgEarth::Util::Controls21;
#else
#include <osgEarthUtil/Controls>
using namespace osgEarth::Util::Controls;
#endif
#ifdef HAVE_OSGEARTH_ELEVATION_QUERY
#include <osgEarth/ElevationQuery>
#include <osgEarthUtil/ObjectLocator>
#else
#include <osgEarthUtil/ElevationManager>
#include <osgEarthUtil/ObjectPlacer>
#endif
#include <osg/ref_ptr>
#include <osgEarth/Version>
#if 0
#include <iostream>
#endif
#include "qgsglobeinterface.h"
#include "qgsglobeplugindialog.h"
#include "qgsrectangle.h"
class QAction;
class QToolBar;
class QgisInterface;
class QDateTime;
class QDockWidget;
class QgsAnnotationItem;
class QgsBillBoardItem;
class QgsGlobeAnnotation;
class QgsGlobeLayerPropertiesFactory;
class QgsGlobeInterface;
class QgsGlobePluginDialog;
class QgsGlobeWidget;
class QgsMapLayer;
class QgsPoint;
class QgsRectangle;
class QgsGlobeFrustumHighlightCallback;
class QgsGlobeFeatureIdentifyCallback;
class QgsGlobeTileSource;
class QgsGlobeVectorLayerConfig;
namespace osgEarth { namespace QtGui { class ViewerWidget; } }
namespace osgEarth { namespace Util { class SkyNode; class VerticalScale; } }
namespace osg
{
class Group;
class Vec3d;
}
namespace osgViewer { class Viewer; }
class GlobePlugin : public QObject, public QgisPlugin
namespace osgEarth
{
class GeoPoint;
class GeoExtent;
class ImageLayer;
class MapNode;
namespace Annotation { class PlaceNode; }
namespace QtGui { class ViewerWidget; }
namespace Util
{
class FeatureHighlightCallback;
class FeatureQueryTool;
class SkyNode;
class VerticalScale;
namespace Controls
{
class Control;
class ControlEventHandler;
class LabelControl;
}
}
}
class GLOBE_EXPORT GlobePlugin : public QObject, public QgisPlugin
{
Q_OBJECT
public:
explicit GlobePlugin( QgisInterface* theQgisInterface );
virtual ~GlobePlugin();
GlobePlugin( QgisInterface* theQgisInterface );
~GlobePlugin();
public slots:
//! offer an interface for python plugins
virtual QgsPluginInterface* pluginInterface();
//! init the gui
virtual void initGui() override;
//! Show the dialog box
void run();
//! Show the settings dialog box
void settings();
//! Reset globe
void reset();
//! unload the plugin
void unload() override;
//! show the help document
void help();
//! Called when a new set of image layers has been received
void imageLayersChanged();
//! Called when a new set of elevation layers has been received
void elevationLayersChanged();
//! Set a different base map (QString::null will disable the base map)
void setBaseMap( QString url );
//! Called when the extents of the map change
void setSkyParameters( bool enabled, const QDateTime& dateTime, bool autoAmbience );
//! Called when the extents of the map change
void extentsChanged();
//! Sync globe extent to mapCanavas
void syncExtent();
#if OSGEARTH_VERSION_GREATER_OR_EQUAL( 2, 5, 0 )
//! Set vertical scale
void setVerticalScale( double scale );
#endif
//! Enable or disable frustum highlight
void enableFrustumHighlight( bool statu );
//! Enable or disable feature identification
void enableFeatureIdentification( bool status );
//! called when a project has been read successfully
void projectReady();
//! called when a new project has been created successfully
void blankProjectReady();
//! called when the globe window is closed
void setGlobeNotRunning();
//! set the globe coordinates of a user right-click on the globe
void setSelectedCoordinates( osg::Vec3d coords );
void setSelectedCoordinates( const osg::Vec3d& coords );
//! get a coordinates vector
osg::Vec3d getSelectedCoordinates();
//! prints the ccordinates in a QMessageBox
void showSelectedCoordinates();
//! emits signal with current mouse coordinates
void showCurrentCoordinates( double lon, double lat );
void showCurrentCoordinates( const osgEarth::GeoPoint &geoPoint );
//! get longitude of user right click
double getSelectedLon();
double getSelectedLon() const { return mSelectedLon; }
//! get latitude of user right click
double getSelectedLat();
double getSelectedLat() const { return mSelectedLat; }
//! get elevation of user right click
double getSelectedElevation();
//! Place an OSG model on the globe
void placeNode( osg::Node* node, double lat, double lon, double alt = 0.0 );
double getSelectedElevation() { return mSelectedElevation; }
//! Get the OSG viewer
osgViewer::Viewer* osgViewer() { return mOsgViewer; }
//! Get OSG map node
osgEarth::MapNode* mapNode() { return mMapNode; }
//! Recursive copy folder
static void copyFolder( QString sourceFolder, QString destFolder );
QgisInterface* qgisIface() const { return mQGisIface; }
public slots:
void run();
void updateLayers();
void showSettings();
void syncExtent();
private:
//! Set HTTP proxy settings
void setupProxy();
//! Setup map
void setupMap();
//! Setup map controls
void setupControls();
private://! Checks if the globe is open
//! Pointer to the QGIS interface object
QgisInterface *mQGisIface;
//!pointer to the qaction for this plugin
QAction * mQActionPointer;
//!pointer to the qaction for this plugin
QAction * mQActionSettingsPointer;
QAction * mQActionUnload;
//! OSG Viewer
osgViewer::Viewer* mOsgViewer;
//! QT viewer widget
QAction* mActionToggleGlobe;
osgEarth::QtGui::ViewerWidget* mViewerWidget;
//! Settings Dialog
QgsGlobePluginDialog *mSettingsDialog;
//! OSG root node
osg::Group* mRootNode;
//! Map node
osgEarth::MapNode* mMapNode;
//! Base layer
osg::ref_ptr<osgEarth::ImageLayer> mBaseLayer;
//! Sky node
osg::ref_ptr<osgEarth::Util::SkyNode> mSkyNode;
#if OSGEARTH_VERSION_GREATER_OR_EQUAL( 2, 5, 0 )
osg::ref_ptr<osgEarth::Util::VerticalScale> mVerticalScale;
#endif
//! QGIS maplayer
osgEarth::ImageLayer* mQgisMapLayer;
//! Tile source
osgEarth::Drivers::QgsOsgEarthTileSource* mTileSource;
//! Control Canvas
ControlCanvas* mControlCanvas;
#ifdef HAVE_OSGEARTH_ELEVATION_QUERY
//! Elevation manager
osgEarth::ElevationQuery* mElevationManager;
//! Object placer
osgEarth::Util::ObjectLocator* mObjectPlacer;
#else
//! Elevation manager
osgEarth::Util::ElevationManager* mElevationManager;
//! Object placer
osgEarth::Util::ObjectPlacer* mObjectPlacer;
#endif
//! tracks if the globe is open
bool mIsGlobeRunning;
//! coordinates of the right-clicked point on the globe
QgsGlobeWidget* mDockWidget;
QgsGlobePluginDialog* mSettingsDialog;
QgsGlobeInterface mGlobeInterface;
QString mBaseLayerUrl;
QList<QgsGlobePluginDialog::LayerDataSource> mImagerySources;
QList<QgsGlobePluginDialog::LayerDataSource> mElevationSources;
double mSelectedLat, mSelectedLon, mSelectedElevation;
#if 0
std::streambuf *mCoutRdBuf, *mCerrRdBuf;
osg::ref_ptr<osgViewer::Viewer> mOsgViewer;
osg::ref_ptr<osgEarth::MapNode> mMapNode;
osg::ref_ptr<osg::Group> mRootNode;
osg::ref_ptr<osgEarth::Util::SkyNode> mSkyNode;
osg::ref_ptr<osgEarth::ImageLayer> mBaseLayer;
osg::ref_ptr<osgEarth::ImageLayer> mQgisMapLayer;
osg::ref_ptr<QgsGlobeTileSource> mTileSource;
QMap<QString, QgsRectangle> mLayerExtents;
osg::ref_ptr<osgEarth::Util::VerticalScale> mVerticalScale;
//! Creates additional pages in the layer properties for adjusting 3D properties
QgsGlobeLayerPropertiesFactory* mLayerPropertiesFactory;
osg::ref_ptr<QgsGlobeFrustumHighlightCallback> mFrustumHighlightCallback;
osg::ref_ptr<QgsGlobeFeatureIdentifyCallback> mFeatureQueryToolIdentifyCb;
// TODO: How to port highlight to 2.7.0?
#if OSGEARTH_VERSION_LESS_THAN(2, 7, 0)
osg::ref_ptr<osgEarth::Util::FeatureHighlightCallback> mFeatureQueryToolHighlightCb;
#endif
osg::ref_ptr<osgEarth::Util::FeatureQueryTool> mFeatureQueryTool;
osg::ref_ptr<osgEarth::Util::Controls::LabelControl> mStatsLabel;
osg::Group* mAnnotationsGroup;
QMap<QString, QMap<QgsBillBoardItem*, osg::ref_ptr<osgEarth::Annotation::PlaceNode> > > mAnnotations;
void setupProxy();
void addControl( osgEarth::Util::Controls::Control* control, int x, int y, int w, int h, osgEarth::Util::Controls::ControlEventHandler* handler );
void addImageControl( const std::string &imgPath, int x, int y, osgEarth::Util::Controls::ControlEventHandler* handler = 0 );
void addModelLayer( QgsVectorLayer* mapLayer , QgsGlobeVectorLayerConfig *layerConfig );
void setupControls();
void applyProjectSettings();
private slots:
void setGlobeEnabled( bool enabled );
void reset();
void projectRead();
void applySettings();
void layerChanged( QgsMapLayer* mapLayer = 0 );
void addBillboard( QgsBillBoardItem* item );
void removeBillboard( QgsBillBoardItem* item );
void refreshQGISMapLayer( QgsRectangle rect = QgsRectangle() );
void updateTileStats( int queued, int tot );
signals:
//! emits current mouse position
@ -192,82 +186,4 @@ class GlobePlugin : public QObject, public QgisPlugin
void newCoordinatesSelected( const QgsPoint & p );
};
class FlyToExtentHandler : public osgGA::GUIEventHandler
{
public:
explicit FlyToExtentHandler( GlobePlugin* globe ) : mGlobe( globe ) { }
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) override;
private:
GlobePlugin* mGlobe;
};
// An event handler that will print out the coordinates at the clicked point
#ifdef HAVE_OSGEARTH_ELEVATION_QUERY
#else
class QueryCoordinatesHandler : public osgGA::GUIEventHandler
{
public:
QueryCoordinatesHandler( GlobePlugin* globe, osgEarth::Util::ElevationManager* elevMan,
const osgEarth::SpatialReference* mapSRS )
: mGlobe( globe ), _mapSRS( mapSRS ), _elevMan( elevMan ) { }
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa );
virtual osg::Vec3d getCoords( float x, float y, osgViewer::View* view, bool getElevation = false );
private:
GlobePlugin* mGlobe;
osg::ref_ptr<const SpatialReference> _mapSRS;
osg::ref_ptr<osgEarth::Util::ElevationManager> _elevMan;
};
#endif
class KeyboardControlHandler : public osgGA::GUIEventHandler
{
public:
explicit KeyboardControlHandler( osgEarth::Util::EarthManipulator* manip ) : _manip( manip ) { }
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) override;
private:
osg::observer_ptr<osgEarth::Util::EarthManipulator> _manip;
};
namespace osgEarth
{
namespace Util
{
#ifdef USE_BACKPORTED_CONTROLS
namespace Controls21
#else
namespace Controls
#endif
{
class NavigationControlHandler : public ControlEventHandler
{
public:
virtual void onMouseDown( class Control* control, int mouseButtonMask ) { Q_UNUSED( control ); Q_UNUSED( mouseButtonMask ); }
virtual void onClick( class Control* control, int mouseButtonMask, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) { Q_UNUSED( control ); Q_UNUSED( mouseButtonMask ); Q_UNUSED( ea ); Q_UNUSED( aa ); }
virtual void onClick( class Control* control, int mouseButtonMask ) override { Q_UNUSED( control ); Q_UNUSED( mouseButtonMask ); }
};
class NavigationControl : public ImageControl
{
public:
explicit NavigationControl( osg::Image* image = nullptr ) : ImageControl( image ), _mouse_down_event( nullptr ) {}
protected:
virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, ControlContext& cx ) override;
private:
osg::ref_ptr<const osgGA::GUIEventAdapter> _mouse_down_event;
};
}
}
}
#endif // QGS_GLOBE_PLUGIN_H

View File

@ -1,6 +1,6 @@
<RCC>
<qresource prefix="/globe/" >
<qresource prefix="/globe">
<file alias="globe.png">images/globe.png</file>
<file alias="icon.svg">images/icon.svg</file>
</qresource>
</RCC>

View File

@ -1,700 +0,0 @@
/***************************************************************************
* globe_plugin_dialog.cpp - settings dialog for the globe plugin
* --------------------------------------
* Date : 11-Nov-2010
* Copyright : (C) 2010 by Marco Bernasocchi
* Email : marco at bernawebdesign.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "globe_plugin_dialog.h"
#include "globe_plugin.h"
#include <qgsapplication.h>
#include <qgsproject.h>
#include <qgsmaplayerregistry.h>
#include <qgsmaplayer.h>
#include <qgslogger.h>
#include <qgscontexthelp.h>
#include <QtAlgorithms>
#include <QtDebug>
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include <QString>
#include <QStringList>
#include <QVariant>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <osg/DisplaySettings>
//constructor
QgsGlobePluginDialog::QgsGlobePluginDialog( QWidget* parent, GlobePlugin* globe, Qt::WindowFlags fl )
: QDialog( parent, fl )
, mGlobe( globe )
{
setupUi( this );
mBaseLayerComboBox->addItem( "Readymap: NASA BlueMarble Imagery", "http://readymap.org/readymap/tiles/1.0.0/1/" );
mBaseLayerComboBox->addItem( "Readymap: NASA BlueMarble with land removed, only ocean", "http://readymap.org/readymap/tiles/1.0.0/2/" );
mBaseLayerComboBox->addItem( "Readymap: High resolution insets from various locations around the world Austin, TX; Kandahar, Afghanistan; Bagram, Afghanistan; Boston, MA; Washington, DC", "http://readymap.org/readymap/tiles/1.0.0/3/" );
mBaseLayerComboBox->addItem( "Readymap: Global Land Cover Facility 15m Landsat", "http://readymap.org/readymap/tiles/1.0.0/6/" );
mBaseLayerComboBox->addItem( "Readymap: NASA BlueMarble + Landsat + Ocean Masking Layer", "http://readymap.org/readymap/tiles/1.0.0/7/" );
mBaseLayerComboBox->addItem( "[Custom]" );
loadStereoConfig(); //values from settings, default values from OSG
setStereoConfig(); //overwrite with values from QSettings
updateStereoDialog(); //update the dialog gui
loadVideoSettings();
loadMapSettings();
elevationPath->setText( QDir::homePath() );
}
//destructor
QgsGlobePluginDialog::~QgsGlobePluginDialog()
{
}
QString QgsGlobePluginDialog::openRasterFile()
{
//see http://www.gdal.org/formats_list.html
QString filter = tr( "GDAL files" ) + " (*.dem *.tif *.tiff *.jpg *.jpeg *.asc);;"
+ tr( "DEM files" ) + " (*.dem);;"
+ tr( "All files" ) + " (*.*)";
QString path = QFileDialog::getOpenFileName( this,
tr( "Open raster file" ),
QDir::homePath(),
filter );
return path;
}
bool QgsGlobePluginDialog::validateResource( QString type, QString uri, QString &error )
{
if ( "Raster" == type )
{
QFileInfo file( uri );
if ( file.isFile() && file.isReadable() )
{
return true;
}
else
{
error = tr( "Invalid Path: The file is either unreadable or does not exist" );
return false;
}
}
else
{
QNetworkAccessManager *manager = new QNetworkAccessManager( this );
QNetworkRequest request;
request.setUrl( QUrl( uri ) );
QNetworkReply *reply = manager->get( request );
//wait for response syncronously
QEventLoop eLoop;
connect( manager, SIGNAL( finished( QNetworkReply * ) ),
&eLoop, SLOT( quit() ) );
eLoop.exec( QEventLoop::ExcludeUserInputEvents );
if ( QNetworkReply::HostNotFoundError != reply->error() )
//FIXME:should be the following line but reply->error() always give "unknown error"
//if (QNetworkReply::NoError == reply->error())
{
QByteArray data = reply->readAll();
QString req( data );
return true;
}
else
{
error = tr( "Invalid URL: " ) + reply->errorString();
return false;
}
}
}
void QgsGlobePluginDialog::showMessageBox( QString text )
{
QMessageBox msgBox;
msgBox.setText( text );
msgBox.exec();
}
void QgsGlobePluginDialog::on_buttonBox_accepted()
{
setStereoConfig();
saveStereoConfig();
saveElevationDatasources();
saveVideoSettings();
saveMapSettings();
accept();
}
void QgsGlobePluginDialog::on_buttonBox_rejected()
{
loadStereoConfig();
setStereoConfig();
readElevationDatasources();
reject();
}
//ELEVATION
void QgsGlobePluginDialog::on_elevationCombo_currentIndexChanged( QString type )
{
elevationPath->setEnabled( true );
if ( "Raster" == type )
{
elevationActions->setCurrentIndex( 0 );
elevationPath->setText( QDir::homePath() );
}
else if ( "Worldwind" == type )
{
elevationActions->setCurrentIndex( 1 );
elevationPath->setText( "http://tileservice.worldwindcentral.com/getTile?bmng.topo.bathy.200401" );
elevationPath->setEnabled( false );
}
else if ( "TMS" == type )
{
elevationActions->setCurrentIndex( 1 );
elevationPath->setText( "http://readymap.org/readymap/tiles/1.0.0/9/" );
}
}
void QgsGlobePluginDialog::on_elevationBrowse_clicked()
{
QString newPath = openRasterFile();
if ( ! newPath.isEmpty() )
{
elevationPath->setText( newPath );
}
}
void QgsGlobePluginDialog::on_elevationAdd_clicked()
{
QString errorText;
bool validationResult = validateResource( elevationCombo->currentText(), elevationPath->text(), errorText );
QMessageBox msgBox;
msgBox.setText( errorText );
msgBox.setInformativeText( tr( "Do you want to add the datasource anyway?" ) );
msgBox.setIcon( QMessageBox::Warning );
msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel );
msgBox.setDefaultButton( QMessageBox::Cancel );
if ( validationResult || msgBox.exec() == QMessageBox::Ok )
{
int i = elevationDatasourcesWidget->rowCount();
QTableWidgetItem *type = new QTableWidgetItem( elevationCombo->currentText() );
QTableWidgetItem *uri = new QTableWidgetItem( elevationPath->text() );
QTableWidgetItem* cache = new QTableWidgetItem();
//cache->setCheckState(( elevationCombo->currentText() == "Worldwind" ) ? Qt::Checked : Qt::Unchecked ); //worldwind_cache will be active
elevationDatasourcesWidget->setRowCount( 1 + i );
elevationDatasourcesWidget->setItem( i, 0, type );
elevationDatasourcesWidget->setItem( i, 1, cache );
elevationDatasourcesWidget->setItem( i, 2, uri );
elevationDatasourcesWidget->setCurrentItem( type, QItemSelectionModel::Clear );
}
}
void QgsGlobePluginDialog::on_elevationRemove_clicked()
{
elevationDatasourcesWidget->removeRow( elevationDatasourcesWidget->currentRow() );
}
void QgsGlobePluginDialog::on_elevationUp_clicked()
{
moveRow( elevationDatasourcesWidget, true );
}
void QgsGlobePluginDialog::on_elevationDown_clicked()
{
moveRow( elevationDatasourcesWidget, false );
}
void QgsGlobePluginDialog::on_mBaseLayerComboBox_currentIndexChanged( int index )
{
QVariant url = mBaseLayerComboBox->itemData( index );
if ( url.isValid() )
{
mBaseLayerURL->setEnabled( false );
mBaseLayerURL->setText( url.toString() );
}
else
{
mBaseLayerURL->setEnabled( true );
}
}
void QgsGlobePluginDialog::moveRow( QTableWidget* widget, bool up )
{
//moves QTableWidget row up or down
if ( widget->selectedItems().count() > 0 )
{
const int sourceRow = widget->currentItem()->row();
const int destRow = ( up ? sourceRow - 1 : sourceRow + 1 );
if ( destRow >= 0 && destRow < widget->rowCount() )
{
// take whole rows
QList<QTableWidgetItem*> sourceItems = takeRow( widget, sourceRow );
QList<QTableWidgetItem*> destItems = takeRow( widget, destRow );
// set back in reverse order
setRow( widget, sourceRow, destItems );
setRow( widget, destRow, sourceItems );
widget->selectRow( destRow );
}
}
}
QList<QTableWidgetItem*> QgsGlobePluginDialog::takeRow( QTableWidget* widget, int row )
{
// takes and returns the whole row
QList<QTableWidgetItem*> rowItems;
for ( int col = 0; col < widget->columnCount(); ++col )
{
rowItems << widget->takeItem( row, col );
}
return rowItems;
}
void QgsGlobePluginDialog::setRow( QTableWidget* widget, int row, const QList<QTableWidgetItem*>& rowItems )
{
// sets the whole row
for ( int col = 0; col < widget->columnCount(); ++col )
{
widget->setItem( row, col, rowItems.at( col ) );
}
}
void QgsGlobePluginDialog::resetElevationDatasources()
{
elevationDatasourcesWidget->clearContents();
elevationDatasourcesWidget->setRowCount( 1 );
elevationDatasourcesWidget->setItem( 0, 0, new QTableWidgetItem( "TMS" ) );
elevationDatasourcesWidget->setItem( 0, 1, new QTableWidgetItem() );
//elevationDatasourcesWidget->item( 0, 1 )->setCheckState( Qt::Unchecked );
elevationDatasourcesWidget->setItem( 0, 2, new QTableWidgetItem( "http://readymap.org/readymap/tiles/1.0.0/9/" ) );
}
void QgsGlobePluginDialog::readElevationDatasources()
{
// clear the widget
elevationDatasourcesWidget->clearContents();
elevationDatasourcesWidget->setRowCount( 0 );
int keysCount = QgsProject::instance()->subkeyList( "Globe-Plugin", "/elevationDatasources/" ).count();
for ( int i = 0; i < keysCount; ++i )
{
QString iNum;
iNum.setNum( i );
QTableWidgetItem *type = new QTableWidgetItem(
QgsProject::instance()->readEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/type" ) );
QTableWidgetItem *uri = new QTableWidgetItem(
QgsProject::instance()->readEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/uri" ) );
//bool cache = QgsProject::instance()->readBoolEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/cache" );
elevationDatasourcesWidget->setRowCount( 1 + i );
elevationDatasourcesWidget->setItem( i, 0, type );
QTableWidgetItem* chkBoxItem = new QTableWidgetItem();
//chkBoxItem->setCheckState( cache ? Qt::Checked : Qt::Unchecked );
elevationDatasourcesWidget->setItem( i, 1, chkBoxItem );
elevationDatasourcesWidget->setItem( i, 2, uri );
}
#if OSGEARTH_VERSION_GREATER_OR_EQUAL( 2, 5, 0 )
double scale = QgsProject::instance()->readDoubleEntry( "Globe-Plugin", "/verticalScale", 1 );
mTxtVerticalScale->setValue( scale );
mGlobe->setVerticalScale( scale );
#endif
}
void QgsGlobePluginDialog::saveElevationDatasources()
{
bool somethingChanged = false;
int keysCount = QgsProject::instance()->subkeyList( "Globe-Plugin", "/elevationDatasources/" ).count();
int rowsCount = elevationDatasourcesWidget->rowCount();
for ( int i = 0; i < rowsCount; ++i )
{
QString iNum;
iNum.setNum( i );
QString typeKey = QgsProject::instance()->readEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/type" );
QString uriKey = QgsProject::instance()->readEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/uri" );
bool cacheKey = QgsProject::instance()->readBoolEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/cache" );
QString type = elevationDatasourcesWidget->item( i, 0 )->text();
QString uri = elevationDatasourcesWidget->item( i, 2 )->text();
bool cache = elevationDatasourcesWidget->item( i, 1 )->checkState();
if ( typeKey != type || uriKey != uri || cacheKey != cache )
{
somethingChanged = true;
QgsProject::instance()->writeEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/type", type );
QgsProject::instance()->writeEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/uri", uri );
QgsProject::instance()->writeEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/cache", cache );
QgsDebugMsg( "editing at " + iNum );
}
else
{
QgsDebugMsg( "nothing to do at " + iNum );
}
}
if ( keysCount > rowsCount )
{
//elminate superfluous keys
somethingChanged = true;
for ( int i = rowsCount; i < keysCount; ++i )
{
QString iNum;
iNum.setNum( i );
QgsDebugMsg( "deleting " + iNum );
QgsProject::instance()->removeEntry( "Globe-Plugin", "/elevationDatasources/L" + iNum + "/" );
}
}
if ( somethingChanged )
{
QgsDebugMsg( "emitting elevationDatasourcesChanged" );
emit elevationDatasourcesChanged();
}
#if OSGEARTH_VERSION_GREATER_OR_EQUAL( 2, 5, 0 )
double scale = mTxtVerticalScale->value();
mGlobe->setVerticalScale( scale );
QgsProject::instance()->writeEntry( "Globe-Plugin", "/verticalScale", scale );
#endif
}
//END ELEVATION
//MODEL
QList<QgsVectorLayer*> QgsGlobePluginDialog::pointLayers()
{
QList<QgsVectorLayer*> list;
QMap< QString, QgsMapLayer *> layers = QgsMapLayerRegistry::instance()->mapLayers();
QMapIterator<QString, QgsMapLayer *> it( layers );
while ( it.hasNext() )
{
it.next();
QgsMapLayer* layer = it.value();
if ( layer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer* vectorLayer = static_cast<QgsVectorLayer*>( layer );
if ( vectorLayer->geometryType() == QGis::Point )
{
list.append( vectorLayer );
}
}
}
return list;
}
void QgsGlobePluginDialog::updatePointLayers()
{
modelLayerCombo->clear();
QList<QgsVectorLayer*> layers = pointLayers();
QListIterator<QgsVectorLayer*> it( layers );
while ( it.hasNext() )
{
QgsVectorLayer* layer = it.next();
modelLayerCombo->addItem( layer->name() );
}
}
QgsVectorLayer* QgsGlobePluginDialog::modelLayer()
{
QList<QgsVectorLayer*> layers = pointLayers();
return ( modelLayerCombo->currentIndex() == -1 ) ? nullptr : layers.at( modelLayerCombo->currentIndex() );
}
void QgsGlobePluginDialog::on_modelBrowse_clicked()
{
//see http://www.openscenegraph.org/projects/osg/wiki/Support/UserGuides/Plugins
QString path = QFileDialog::getOpenFileName( this,
tr( "Open 3D model file" ),
QDir::homePath(),
tr( "Model files" ) + " (*.3dc *.asc *.3ds *.ac *.bsp *.dae *.dw *.dxf *.fbx *.gem *.geo *.iv *.wrl *.ive *.logo *.lwo *.lw *.geo *.lws *.md2 *.obj *.ogr *.flt *.osg *.shp *.stl *.sta *.wrl *.x);;"
+ tr( "All files" ) + " (*.*)"
);
if ( ! path.isEmpty() )
{
modelPathLineEdit->setText( path );
}
}
//END MODEL
//STEREO
void QgsGlobePluginDialog::on_resetStereoDefaults_clicked()
{
//http://www.openscenegraph.org/projects/osg/wiki/Support/UserGuides/StereoSettings
comboStereoMode->setCurrentIndex( comboStereoMode->findText( "OFF" ) );
screenDistance->setValue( 0.5 );
screenHeight->setValue( 0.26 );
screenWidth->setValue( 0.325 );
eyeSeparation->setValue( 0.06 );
splitStereoHorizontalSeparation->setValue( 42 );
splitStereoVerticalSeparation->setValue( 42 );
splitStereoHorizontalEyeMapping->setCurrentIndex( 0 );
splitStereoVerticalEyeMapping->setCurrentIndex( 0 );
}
void QgsGlobePluginDialog::on_comboStereoMode_currentIndexChanged( QString value )
{
Q_UNUSED( value );
setStereoMode();
updateStereoDialog();
}
void QgsGlobePluginDialog::on_eyeSeparation_valueChanged( double value )
{
osg::DisplaySettings::instance()->setEyeSeparation( value );
}
void QgsGlobePluginDialog::on_screenDistance_valueChanged( double value )
{
osg::DisplaySettings::instance()->setScreenDistance( value );
}
void QgsGlobePluginDialog::on_screenWidth_valueChanged( double value )
{
osg::DisplaySettings::instance()->setScreenWidth( value );
}
void QgsGlobePluginDialog::on_screenHeight_valueChanged( double value )
{
osg::DisplaySettings::instance()->setScreenHeight( value );
}
void QgsGlobePluginDialog::on_splitStereoHorizontalSeparation_valueChanged( int value )
{
osg::DisplaySettings::instance()->setSplitStereoHorizontalSeparation( value );
}
void QgsGlobePluginDialog::on_splitStereoVerticalSeparation_valueChanged( int value )
{
osg::DisplaySettings::instance()->setSplitStereoVerticalSeparation( value );
}
void QgsGlobePluginDialog::on_splitStereoHorizontalEyeMapping_currentIndexChanged( int value )
{
osg::DisplaySettings::instance()->setSplitStereoHorizontalEyeMapping(
( osg::DisplaySettings::SplitStereoHorizontalEyeMapping ) value );
}
void QgsGlobePluginDialog::on_splitStereoVerticalEyeMapping_currentIndexChanged( int value )
{
osg::DisplaySettings::instance()->setSplitStereoVerticalEyeMapping(
( osg::DisplaySettings::SplitStereoVerticalEyeMapping ) value );
}
void QgsGlobePluginDialog::loadStereoConfig()
{
comboStereoMode->setCurrentIndex( comboStereoMode->findText( settings.value( "/Plugin-Globe/stereoMode",
"OFF" ).toString() ) );
screenDistance->setValue( settings.value( "/Plugin-Globe/screenDistance",
osg::DisplaySettings::instance()->getScreenDistance() ).toDouble() );
screenWidth->setValue( settings.value( "/Plugin-Globe/screenWidth",
osg::DisplaySettings::instance()->getScreenWidth() ).toDouble() );
screenHeight->setValue( settings.value( "/Plugin-Globe/screenHeight",
osg::DisplaySettings::instance()->getScreenHeight() ).toDouble() );
eyeSeparation->setValue( settings.value( "/Plugin-Globe/eyeSeparation",
osg::DisplaySettings::instance()->getEyeSeparation() ).toDouble() );
splitStereoHorizontalSeparation->setValue( settings.value( "/Plugin-Globe/splitStereoHorizontalSeparation",
osg::DisplaySettings::instance()->getSplitStereoHorizontalSeparation() ).toInt() );
splitStereoVerticalSeparation->setValue( settings.value( "/Plugin-Globe/splitStereoVerticalSeparation",
osg::DisplaySettings::instance()->getSplitStereoVerticalSeparation() ).toInt() );
splitStereoHorizontalEyeMapping->setCurrentIndex( settings.value( "/Plugin-Globe/splitStereoHorizontalEyeMapping",
osg::DisplaySettings::instance()->getSplitStereoHorizontalEyeMapping() ).toInt() );
splitStereoVerticalEyeMapping->setCurrentIndex( settings.value( "/Plugin-Globe/splitStereoVerticalEyeMapping",
osg::DisplaySettings::instance()->getSplitStereoVerticalEyeMapping() ).toInt() );
}
void QgsGlobePluginDialog::setStereoMode()
{
//http://www.openscenegraph.org/projects/osg/wiki/Support/UserGuides/StereoSettings
//http://www.openscenegraph.org/documentation/OpenSceneGraphReferenceDocs/a00181.html
QString stereoMode = comboStereoMode->currentText();
if ( "OFF" == stereoMode )
{
osg::DisplaySettings::instance()->setStereo( false );
}
else
{
osg::DisplaySettings::instance()->setStereo( true );
if ( "ANAGLYPHIC" == stereoMode )
{
osg::DisplaySettings::instance()->setStereoMode( osg::DisplaySettings::ANAGLYPHIC );
}
else if ( "VERTICAL_SPLIT" == stereoMode )
{
osg::DisplaySettings::instance()->setStereoMode( osg::DisplaySettings::VERTICAL_SPLIT );
}
else if ( "HORIZONTAL_SPLIT" == stereoMode )
{
osg::DisplaySettings::instance()->setStereoMode( osg::DisplaySettings::HORIZONTAL_SPLIT );
}
else if ( "QUAD_BUFFER" == stereoMode )
{
osg::DisplaySettings::instance()->setStereoMode( osg::DisplaySettings::QUAD_BUFFER );
}
else
{
//should never get here
QMessageBox msgBox;
msgBox.setText( "This stereo mode has not been implemented yet. Defaulting to ANAGLYPHIC" );
msgBox.exec();
}
}
}
void QgsGlobePluginDialog::loadVideoSettings()
{
mAntiAliasingGroupBox->setChecked( settings.value( "/Plugin-Globe/anti-aliasing", false ).toBool() );
mAANumSamples->setValidator( new QIntValidator( mAANumSamples ) );
mAANumSamples->setText( settings.value( "/Plugin-Globe/anti-aliasing-level", "" ).toString() );
}
void QgsGlobePluginDialog::saveVideoSettings()
{
settings.setValue( "/Plugin-Globe/anti-aliasing", mAntiAliasingGroupBox->isChecked() );
settings.setValue( "/Plugin-Globe/anti-aliasing-level", mAANumSamples->text() );
}
void QgsGlobePluginDialog::loadMapSettings()
{
mBaseLayerGroupBox->setChecked( settings.value( "/Plugin-Globe/baseLayerEnabled", true ).toBool() );
QString mapUrl = settings.value( "/Plugin-Globe/baseLayerURL", "http://readymap.org/readymap/tiles/1.0.0/7/" ).toString();
int urlIndex = mBaseLayerComboBox->findData( mapUrl );
if ( urlIndex != -1 )
{
mBaseLayerComboBox->setCurrentIndex( urlIndex );
}
else
{
mBaseLayerComboBox->setCurrentIndex( mBaseLayerComboBox->findData( QVariant() ) );
}
mBaseLayerURL->setText( mapUrl );
mSkyGroupBox->setChecked( settings.value( "/Plugin-Globe/skyEnabled", false ).toBool() );
mSkyAutoAmbient->setChecked( settings.value( "/Plugin-Globe/skyAutoAmbient", false ).toBool() );
mSkyDateTime->setDateTime( settings.value( "/Plugin-Globe/skyDateTime", QDateTime() ).toDateTime() );
}
void QgsGlobePluginDialog::saveMapSettings()
{
settings.setValue( "/Plugin-Globe/baseLayerEnabled", mBaseLayerGroupBox->isChecked() );
settings.setValue( "/Plugin-Globe/baseLayerURL", mBaseLayerURL->text() );
// Let globe update the current view
if ( mBaseLayerGroupBox->isChecked() )
{
mGlobe->setBaseMap( mBaseLayerURL->text() );
}
else
{
mGlobe->setBaseMap( QString::null );
}
settings.setValue( "/Plugin-Globe/skyEnabled", mSkyGroupBox->isChecked() );
settings.setValue( "/Plugin-Globe/skyAutoAmbient", mSkyAutoAmbient->isChecked() );
settings.setValue( "/Plugin-Globe/skyDateTime", mSkyDateTime->dateTime() );
// Adjust sky of a running globe viewer
mGlobe->setSkyParameters( mSkyGroupBox->isChecked(), mSkyDateTime->dateTime(), mSkyAutoAmbient->isChecked() );
}
void QgsGlobePluginDialog::setStereoConfig()
{
osgViewer::Viewer* viewer = mGlobe->osgViewer();
if ( viewer )
{
viewer->getDatabasePager()->clear();
//SETTING THE VALUES IN THE OEGearth instance
setStereoMode();
osg::DisplaySettings::instance()->setScreenDistance( screenDistance->value() );
osg::DisplaySettings::instance()->setScreenWidth( screenWidth->value() );
osg::DisplaySettings::instance()->setScreenHeight( screenHeight->value() );
osg::DisplaySettings::instance()->setEyeSeparation( eyeSeparation->value() );
osg::DisplaySettings::instance()->setSplitStereoHorizontalSeparation( splitStereoHorizontalSeparation->value() );
osg::DisplaySettings::instance()->setSplitStereoVerticalSeparation( splitStereoVerticalSeparation->value() );
osg::DisplaySettings::instance()->setSplitStereoHorizontalEyeMapping(
( osg::DisplaySettings::SplitStereoHorizontalEyeMapping ) splitStereoHorizontalEyeMapping->currentIndex() );
osg::DisplaySettings::instance()->setSplitStereoVerticalEyeMapping(
( osg::DisplaySettings::SplitStereoVerticalEyeMapping ) splitStereoVerticalEyeMapping->currentIndex() );
}
}
void QgsGlobePluginDialog::saveStereoConfig()
{
settings.setValue( "/Plugin-Globe/stereoMode", comboStereoMode->currentText() );
settings.setValue( "/Plugin-Globe/screenDistance", screenDistance->value() );
settings.setValue( "/Plugin-Globe/screenWidth", screenWidth->value() );
settings.setValue( "/Plugin-Globe/screenHeight", screenHeight->value() );
settings.setValue( "/Plugin-Globe/eyeSeparation", eyeSeparation->value() );
settings.setValue( "/Plugin-Globe/splitStereoHorizontalSeparation", splitStereoHorizontalSeparation->value() );
settings.setValue( "/Plugin-Globe/splitStereoVerticalSeparation", splitStereoVerticalSeparation->value() );
settings.setValue( "/Plugin-Globe/splitStereoHorizontalEyeMapping", splitStereoHorizontalEyeMapping->currentIndex() );
settings.setValue( "/Plugin-Globe/splitStereoVerticalEyeMapping", splitStereoVerticalEyeMapping->currentIndex() );
}
void QgsGlobePluginDialog::updateStereoDialog()
{
QString stereoMode = comboStereoMode->currentText();
screenDistance->setEnabled( true );
screenHeight->setEnabled( true );
screenWidth->setEnabled( true );
eyeSeparation->setEnabled( true );
splitStereoHorizontalSeparation->setEnabled( false );
splitStereoVerticalSeparation->setEnabled( false );
splitStereoHorizontalEyeMapping->setEnabled( false );
splitStereoVerticalEyeMapping->setEnabled( false );
if ( "OFF" == stereoMode )
{
screenDistance->setEnabled( false );
screenHeight->setEnabled( false );
screenWidth->setEnabled( false );
eyeSeparation->setEnabled( false );
}
else if ( "ANAGLYPHIC" == stereoMode )
{
//nothing to do
}
else if ( "VERTICAL_SPLIT" == stereoMode )
{
splitStereoVerticalSeparation->setEnabled( true );
splitStereoVerticalEyeMapping->setEnabled( true );
}
else if ( "HORIZONTAL_SPLIT" == stereoMode )
{
splitStereoHorizontalSeparation->setEnabled( true );
splitStereoHorizontalEyeMapping->setEnabled( true );
}
else if ( "QUAD_BUFFER" == stereoMode )
{
//nothing to do
}
else
{
//should never get here
QMessageBox msgBox;
msgBox.setText( "This stereo mode has not been implemented yet." );
msgBox.exec();
}
}
//END STEREO

View File

@ -1,104 +0,0 @@
/***************************************************************************
globe_plugin_dialog.h - settings dialog for the globe plugin
--------------------------------------
Date : 11-Nov-2010
Copyright : (C) 2010 by Marco Bernasocchi
Email : marco at bernawebdesign.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGIS_GLOBE_PLUGIN_DIALOG_H
#define QGIS_GLOBE_PLUGIN_DIALOG_H
#include <ui_globe_plugin_dialog_guibase.h>
#include <QDialog>
#include <QSettings>
#include <QCheckBox>
#include <osgViewer/Viewer>
#include "qgscontexthelp.h"
#include <qgsproject.h>
#include <qgsvectorlayer.h>
class GlobePlugin;
class QgsGlobePluginDialog: public QDialog, private Ui::QgsGlobePluginDialogGuiBase
{
Q_OBJECT
public:
QgsGlobePluginDialog( QWidget * parent, GlobePlugin* globe, Qt::WindowFlags fl = 0 );
~QgsGlobePluginDialog();
void resetElevationDatasources();
void readElevationDatasources();
QTableWidget *elevationDatasources() { return elevationDatasourcesWidget; }
void updatePointLayers();
QgsVectorLayer* modelLayer();
QString modelPath() { return modelPathLineEdit->text(); }
private:
QString openRasterFile();
void updateStereoDialog();
bool validateResource( QString type, QString uri, QString& error );
void saveElevationDatasources();
void moveRow( QTableWidget* widget, bool up );
QList<QTableWidgetItem*> takeRow( QTableWidget* widget, int row );
void setRow( QTableWidget* widget, int row, const QList< QTableWidgetItem* >& rowItems );
void showMessageBox( QString text );
QList<QgsVectorLayer*> pointLayers();
//! Set osg/DisplaySettings
void setStereoConfig();
//! Init dialog from settings using defaults from osg/DisplaySettings
void loadStereoConfig();
//! Save settings
void saveStereoConfig();
//! Handle stereoMode
void setStereoMode();
void loadVideoSettings();
void saveVideoSettings();
void loadMapSettings();
void saveMapSettings();
private slots:
void on_buttonBox_accepted();
void on_buttonBox_rejected();
//STEREO
void on_comboStereoMode_currentIndexChanged( QString value );
void on_eyeSeparation_valueChanged( double value );
void on_screenDistance_valueChanged( double value );
void on_screenWidth_valueChanged( double value );
void on_screenHeight_valueChanged( double value );
void on_splitStereoHorizontalSeparation_valueChanged( int value );
void on_splitStereoVerticalSeparation_valueChanged( int value );
void on_splitStereoHorizontalEyeMapping_currentIndexChanged( int value );
void on_splitStereoVerticalEyeMapping_currentIndexChanged( int value );
void on_resetStereoDefaults_clicked();
//MODEL
void on_modelBrowse_clicked();
//ELEVATION
void on_elevationCombo_currentIndexChanged( QString type );
void on_elevationBrowse_clicked();
void on_elevationAdd_clicked();
void on_elevationRemove_clicked();
void on_elevationUp_clicked();
void on_elevationDown_clicked();
//MAP
void on_mBaseLayerComboBox_currentIndexChanged( int index );
signals:
void elevationDatasourcesChanged();
private:
GlobePlugin* mGlobe;
QSettings settings;
};
#endif // QGIS_GLOBE_PLUGIN_DIALOG_H

View File

@ -1,782 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsGlobePluginDialogGuiBase</class>
<widget class="QDialog" name="QgsGlobePluginDialogGuiBase">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1407</width>
<height>534</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Globe Settings</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>../../.designer/backup</normaloff>../../.designer/backup</iconset>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Map</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QGroupBox" name="mBaseLayerGroupBox">
<property name="title">
<string>Base Layer</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>URL</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="mBaseLayerComboBox"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mBaseLayerURL"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="mSkyGroupBox">
<property name="title">
<string>Sky</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Date / Time (UTC)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDateTimeEdit" name="mSkyDateTime">
<property name="displayFormat">
<string>dd.MM.yyyy HH:mm</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="mSkyAutoAmbient">
<property name="text">
<string>Auto ambient</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="elevation">
<attribute name="title">
<string>Elevation</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="mTxtVerticalScale"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Vertical Scale</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="elevationUp">
<property name="text">
<string>Up</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="elevationDown">
<property name="text">
<string>Down</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="elevationAdd">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="elevationRemove">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>URL/File</string>
</property>
<property name="buddy">
<cstring>elevationPath</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="elevationPath">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="elevationActions">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="elevationIsLocal">
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QPushButton" name="elevationBrowse">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>27</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="elevationIsRemote">
<layout class="QGridLayout" name="gridLayout_6"/>
</widget>
</widget>
</item>
</layout>
</item>
<item row="5" column="0" colspan="2">
<widget class="QTableWidget" name="elevationDatasourcesWidget">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragEnabled">
<bool>false</bool>
</property>
<property name="dragDropOverwriteMode">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::NoDragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::IgnoreAction</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="showGrid">
<bool>true</bool>
</property>
<property name="gridStyle">
<enum>Qt::SolidLine</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="rowCount">
<number>0</number>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>100</number>
</attribute>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Type</string>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
</column>
<column>
<property name="text">
<string>Cache</string>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
</column>
<column>
<property name="text">
<string>Path</string>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
</column>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Type</string>
</property>
<property name="buddy">
<cstring>elevationCombo</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="elevationCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Raster</string>
</property>
</item>
<item>
<property name="text">
<string>TMS</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="video">
<attribute name="title">
<string>Video</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0">
<widget class="QGroupBox" name="mAntiAliasingGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Anti Aliasing</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Samples</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mAANumSamples">
<property name="placeholderText">
<string>[Leave empty for maximum]</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>&lt;i&gt;Changing video settings requires a restart of the globe plugin&lt;/i&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="model">
<attribute name="title">
<string>Model</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Point Layer</string>
</property>
<property name="buddy">
<cstring>modelLayerCombo</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>3D Model</string>
</property>
<property name="buddy">
<cstring>modelPathLineEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="modelPathLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="modelBrowse">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>27</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="modelLayerCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="stereo">
<attribute name="title">
<string>Stereo</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="comboStereoModeLabel">
<property name="text">
<string>Stereo Mode</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="screenDistanceLabel">
<property name="text">
<string>Screen distance (m)</string>
</property>
<property name="buddy">
<cstring>screenDistance</cstring>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QDoubleSpinBox" name="screenDistance">
<property name="accelerated">
<bool>true</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="screenWidthLabel">
<property name="text">
<string>Screen width (m)</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QDoubleSpinBox" name="screenWidth">
<property name="accelerated">
<bool>true</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<widget class="QLabel" name="splitStereoHorizontalSeparationLabel">
<property name="text">
<string>Split stereo horizontal separation (px)</string>
</property>
</widget>
</item>
<item row="13" column="0" colspan="2">
<widget class="QLabel" name="splitStereoVerticalSeparationLabel">
<property name="text">
<string>Split stereo vertical separation (px)</string>
</property>
</widget>
</item>
<item row="15" column="0" colspan="2">
<widget class="QLabel" name="splitStereoVerticalEyeMappingLabel">
<property name="text">
<string>Split stereo vertical eye mapping</string>
</property>
</widget>
</item>
<item row="15" column="2">
<widget class="QComboBox" name="splitStereoVerticalEyeMapping">
<property name="enabled">
<bool>true</bool>
</property>
<item>
<property name="text">
<string notr="true">LEFT_EYE_TOP_VIEWPORT</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">LEFT_EYE_BOTTOM_VIEWPORT</string>
</property>
</item>
</widget>
</item>
<item row="8" column="2">
<widget class="QDoubleSpinBox" name="screenHeight">
<property name="accelerated">
<bool>true</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="screenHeightLabel">
<property name="text">
<string>Screen height (m)</string>
</property>
</widget>
</item>
<item row="13" column="2">
<widget class="QSpinBox" name="splitStereoVerticalSeparation">
<property name="accelerated">
<bool>true</bool>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QSpinBox" name="splitStereoHorizontalSeparation">
<property name="enabled">
<bool>true</bool>
</property>
<property name="accelerated">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="comboStereoMode">
<item>
<property name="text">
<string notr="true">OFF</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">ANAGLYPHIC</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">QUAD_BUFFER</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">HORIZONTAL_SPLIT</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">VERTICAL_SPLIT</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="eyeSeparationLabel">
<property name="text">
<string>Eye separation (m)</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QDoubleSpinBox" name="eyeSeparation">
<property name="readOnly">
<bool>false</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="accelerated">
<bool>true</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
</widget>
</item>
<item row="16" column="2">
<widget class="QPushButton" name="resetStereoDefaults">
<property name="text">
<string>Reset to defaults</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="splitStereoHorizontalEyeMappingLabel">
<property name="text">
<string>Split stereo horizontal eye mapping</string>
</property>
</widget>
</item>
<item row="11" column="2">
<widget class="QComboBox" name="splitStereoHorizontalEyeMapping">
<item>
<property name="text">
<string notr="true">LEFT_EYE_LEFT_VIEWPORT</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">LEFT_EYE_RIGHT_VIEWPORT</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>comboStereoMode</tabstop>
<tabstop>eyeSeparation</tabstop>
<tabstop>screenDistance</tabstop>
<tabstop>screenWidth</tabstop>
<tabstop>screenHeight</tabstop>
<tabstop>splitStereoHorizontalSeparation</tabstop>
<tabstop>splitStereoHorizontalEyeMapping</tabstop>
<tabstop>splitStereoVerticalSeparation</tabstop>
<tabstop>splitStereoVerticalEyeMapping</tabstop>
<tabstop>resetStereoDefaults</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QgsGlobePluginDialogGuiBase</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>446</x>
<y>529</y>
</hint>
<hint type="destinationlabel">
<x>481</x>
<y>297</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QgsGlobePluginDialogGuiBase</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>387</x>
<y>529</y>
</hint>
<hint type="destinationlabel">
<x>281</x>
<y>339</y>
</hint>
</hints>
</connection>
</connections>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 311 B

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 272 B

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

After

Width:  |  Height:  |  Size: 160 B

View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2996"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="icon.svg">
<defs
id="defs2998">
<linearGradient
id="linearGradient3948">
<stop
style="stop-color:#14c412;stop-opacity:1;"
offset="0"
id="stop3950" />
<stop
style="stop-color:#2fa92d;stop-opacity:1;"
offset="1"
id="stop3952" />
</linearGradient>
<linearGradient
id="linearGradient3860">
<stop
style="stop-color:#cfddee;stop-opacity:1;"
offset="0"
id="stop3862" />
<stop
style="stop-color:#6793cd;stop-opacity:1;"
offset="1"
id="stop3864" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3860"
id="radialGradient3870"
cx="42.630283"
cy="18.727272"
fx="42.630283"
fy="18.727272"
r="31.787046"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.79604311,0,0,-1,87.02645,34.545452)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3948"
id="linearGradient3954"
x1="1.8088502"
y1="29.950056"
x2="62.28172"
y2="29.950056"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11"
inkscape:cx="30.353097"
inkscape:cy="32.680944"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1028"
inkscape:window-x="0"
inkscape:window-y="867"
inkscape:window-maximized="1" />
<metadata
id="metadata3001">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
style="opacity:1;fill:url(#radialGradient3870);fill-opacity:1;fill-rule:evenodd;stroke:#326fcb;stroke-width:2.66500000000000004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-linejoin:round"
d="m 62.363635,32.454544 c 0,16.819581 -13.63496,30.454546 -30.454545,30.454546 -16.819581,0 -30.4545465,-13.634965 -30.4545465,-30.454546 0,-16.819581 13.6349655,-30.4545464 30.4545465,-30.4545464 16.819585,0 30.454545,13.6349654 30.454545,30.4545464 z"
id="path3036"
inkscape:connector-curvature="0" />
<g
id="g3941"
style="fill:url(#linearGradient3954);fill-opacity:1">
<path
sodipodi:nodetypes="csszszssssssssssc"
inkscape:connector-curvature="0"
id="path3807"
d="m 12.454545,53.090909 c 1.274253,-0.234239 0.987012,-1.887258 1.167988,-3.342749 0.14498,-1.165998 0.94868,-2.074964 0.426375,-2.997098 C 13.206543,45.26386 10.665333,45.173915 10.090909,44.727273 9.5164846,44.28063 6.2081861,39.649018 4.2602054,38.122499 2.7215555,36.916749 2.4418971,38.844949 2.1818184,38 1.9217398,37.155052 1.3372634,30.593092 3.1337285,24.323806 3.5115035,23.00545 7.1602709,22.238388 7.515887,20.991567 7.8164462,19.93778 6.145546,20.97674 6.5045705,19.949524 6.9292731,18.734395 8.5422106,18.772373 8.9712963,17.539473 9.3487965,16.454795 7.2886825,16.299144 7.3366292,14.911299 c 0.047818,-1.384128 2.5672416,-2.909759 3.0101188,-3.832106 0.501632,-1.044709 3.989113,1.131964 4.453467,0.186338 1.360061,-2.7696803 3.77755,-2.9357004 4.238968,-4.6431458 C 20.135902,2.5640536 9.8124841,10.776552 9.5555349,11.098355 -5.3352534,29.747591 5.3140435,47.482146 8.153283,51.536495 c 0.8794239,1.255791 2.256379,1.571058 4.301262,1.554414 z"
style="fill:url(#linearGradient3954);stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;opacity:1" />
<path
sodipodi:nodetypes="zssszzsszsssssssssszssssszszzzsssssszzzzssz"
inkscape:connector-curvature="0"
id="path3809"
d="m 27.636364,21.090909 c 0.780036,-0.268848 3.841437,-0.393949 5.865311,0.466598 1.560421,0.663488 1.932626,2.226274 3.705311,2.820447 1.73958,0.583077 1.719271,-1.07816 3.166476,-0.925882 1.979473,0.208285 5.200248,1.909349 5.626538,-0.04298 0.42629,-1.952329 -3.482539,-1.564576 -3.636364,-1.954546 -0.153825,-0.38997 -0.907464,-2.20096 -1.367687,-2.219935 -0.792951,-0.0327 0.05341,1.647316 -0.882662,1.834095 -0.870354,0.173666 -3.564327,-3.908646 -3.749651,-4.114159 -0.185324,-0.205513 -3.658196,-1.030126 0.01227,1.393627 0.660651,0.436254 1.06746,1.248195 0.99089,1.616479 -0.0805,0.387187 -1.377987,-0.797843 -2.012248,-1.182769 -0.568931,-0.345277 -1.250482,-2.173596 -2.841505,-1.6363 -2.980321,1.006469 -4.410452,3.689536 -6.306909,4.235529 -1.803183,0.519139 -2.182124,-2.658666 -1.606749,-3.390722 0.731477,-0.930665 5.771549,0.199111 2.985466,-2.11817 -1.634495,-1.359465 0.951504,-1.857968 2.952757,-2.427455 0.540886,-0.153917 1.479538,-2.697608 2.652906,-2.949768 0.92167,-0.19807 1.977272,1.678944 2.534156,1.538303 2.61531,-0.660493 3.627299,-0.856397 4.138969,-1.669664 C 40.375306,9.5503696 38.831377,9.3355454 38.64865,8.1414392 38.536654,7.4095538 39.959296,6.3562427 38.992557,6.2706175 37.822051,6.1669445 37.22735,10.955693 35.695763,11.099921 34.674286,11.196113 33.201042,9.9657489 32.225228,9.5607789 29.616386,8.4780901 31.824133,7.6684294 34.175191,6.3965729 c 1.748176,-0.9457141 2.377964,-1.780523 6.370263,-1.6693002 3.992299,0.1112228 8.320174,2.5394347 11.552346,4.9160824 3.077189,2.2626879 4.273435,3.9476669 5.674927,5.9475539 1.401492,1.999888 2.5305,4.587181 3.589725,7.834384 1.059224,3.247202 1.320981,5.502969 0.155378,7.463313 -1.165603,1.960344 -1.125444,7.239011 -1.704848,2.703117 -0.687643,-5.383243 -2.822899,-4.992543 -3.649927,-5.46511 -1.684387,-0.962463 -2.790222,-0.440248 -1.184328,0.59583 2.066408,1.333188 -1.199397,3.659878 -2.461262,4.238816 -4.151366,1.904629 -2.566664,-0.580367 -3.554528,-2.528722 -1.266813,-2.498526 -6.400697,-10.413787 -1.731214,0.204992 2.00796,4.56626 6.0178,4.429608 5.495549,5.726108 -0.522251,1.2965 -2.494318,0.151757 -4.636363,5.454545 -2.142044,5.302788 0.550185,7.981654 -6.636364,12.590909 -7.186548,4.609255 -7.004448,-12.805096 -7.103729,-14.598635 -0.09928,-1.793539 -4.961949,-2.510136 -8.446558,-1.524932 -2.274119,0.642963 -5.891641,-5.638639 -5.73453,-7.377525 0.418624,-4.633269 6.6866,-9.548242 7.466636,-9.81709 z"
style="opacity:1;fill:url(#linearGradient3954);fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:nodetypes="zsszszsz"
inkscape:connector-curvature="0"
id="path3807-9"
d="m 26.626118,12.261844 c 0.506237,-0.183147 -0.826308,1.374667 0.633897,1.236797 1.156344,-0.10918 2.903225,-0.302237 2.38092,-1.224371 -0.842365,-1.487202 -1.264763,-0.94766 -1.480726,-1.978334 -0.215963,-1.0306751 -1.366307,-1.8392743 -1.537059,0.148182 -0.05106,0.594306 -1.615575,0.735346 -1.822054,1.161566 -0.206478,0.42622 -0.210556,1.244186 0.150041,1.3492 0.388335,0.113093 1.168743,-0.509893 1.674981,-0.69304 z"
style="opacity:1;fill:url(#linearGradient3954);fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:nodetypes="zzzz"
inkscape:connector-curvature="0"
id="path3807-9-7"
d="M 23.212662,6.8486211 C 24.138782,6.4601476 22.794749,5.6960066 21.162652,6.771003 19.530555,7.8459993 20.48825,7.5611724 20.862716,7.6702259 21.237182,7.7792794 22.286543,7.2370945 23.212662,6.8486211 z"
style="opacity:1;fill:url(#linearGradient3954);fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:nodetypes="zzzz"
inkscape:connector-curvature="0"
id="path3807-9-1"
d="m 49.173839,50.447542 c 1.593614,0.222363 0.694273,-0.948645 2.250125,-4.038377 1.555851,-3.089731 -1.088018,-0.634888 -1.762048,0.59816 -0.674029,1.233047 -2.081692,3.217854 -0.488077,3.440217 z"
style="opacity:1;fill:url(#linearGradient3954);fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
<path
inkscape:connector-curvature="0"
id="path3858"
d="m 62.363635,32.454544 c 0,16.819581 -13.63496,30.454546 -30.454545,30.454546 -16.819581,0 -30.4545465,-13.634965 -30.4545465,-30.454546 0,-16.819581 13.6349655,-30.4545464 30.4545465,-30.4545464 16.819585,0 30.454545,13.6349654 30.454545,30.4545464 z"
style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#326fcb;stroke-width:2.66500000000000004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-linejoin:round" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -1,92 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
* Copyright 2008-2012 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTHQT_COMMON_H
#define OSGEARTHQT_COMMON_H 1
#include <osgEarth/Common>
//#include <osgEarthAnnotation/AnnotationNode>
#include <osgViewer/Viewer>
// define USE_DEPRECATED_API is used to include in API which is being phased out
// if you can compile your apps with this turned off you are
// well placed for compatibility with future versions.
#define USE_DEPRECATED_API
#if defined(_MSC_VER)
#pragma warning( disable : 4244 )
#pragma warning( disable : 4251 )
#pragma warning( disable : 4267 )
#pragma warning( disable : 4275 )
#pragma warning( disable : 4290 )
#pragma warning( disable : 4786 )
#pragma warning( disable : 4305 )
#pragma warning( disable : 4996 )
#endif
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__)
# if defined( OSGEARTHQT_LIBRARY_STATIC )
# define OSGEARTHQT_EXPORT
# elif defined( OSGEARTHQT_LIBRARY )
# define OSGEARTHQT_EXPORT __declspec(dllexport)
# else
# define OSGEARTHQT_EXPORT __declspec(dllimport)
# endif
#else
# define OSGEARTHQT_EXPORT
#endif
// set up define for whether member templates are supported by VisualStudio compilers.
#ifdef _MSC_VER
# if (_MSC_VER >= 1300)
# define __STL_MEMBER_TEMPLATES
# endif
#endif
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
#ifndef OSG_MIN_VERSION_REQUIRED
#define OSG_MIN_VERSION_REQUIRED(MAJOR, MINOR, PATCH) ((OPENSCENEGRAPH_MAJOR_VERSION>MAJOR) || (OPENSCENEGRAPH_MAJOR_VERSION==MAJOR && (OPENSCENEGRAPH_MINOR_VERSION>MINOR || (OPENSCENEGRAPH_MINOR_VERSION==MINOR && OPENSCENEGRAPH_PATCH_VERSION>=PATCH))))
#endif
#ifndef OSG_VERSION_LESS_THAN
#define OSG_VERSION_LESS_THAN(MAJOR, MINOR, PATCH) ((OPENSCENEGRAPH_MAJOR_VERSION<MAJOR) || (OPENSCENEGRAPH_MAJOR_VERSION==MAJOR && (OPENSCENEGRAPH_MINOR_VERSION<MINOR || (OPENSCENEGRAPH_MINOR_VERSION==MINOR && OPENSCENEGRAPH_PATCH_VERSION<PATCH))))
#endif
/**
\namespace osgEarthQt
*/
namespace osgEarth { namespace QtGui {
//typedef std::vector< osg::ref_ptr<osgEarth::Annotation::AnnotationNode> > AnnotationVector;
typedef std::vector< osg::ref_ptr<osgViewer::View> > ViewVector;
} }
#endif // OSGEARTHQT_COMMON_H

View File

@ -1,91 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
* Copyright 2008-2012 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTHQT_VIEWERWIDGET_H
#define OSGEARTHQT_VIEWERWIDGET_H 1
//#include <osgEarthQt/Common>
#include "Common"
#include <osgEarth/Map>
#include <osgQt/GraphicsWindowQt>
#include <osgViewer/ViewerBase>
#include <QtCore/QTimer>
#undef OSGEARTHQT_EXPORT
#define OSGEARTHQT_EXPORT
namespace osgEarth { namespace QtGui
{
using namespace osgEarth;
/**
* Qt widget that encapsulates an osgViewer::Viewer.
*/
class OSGEARTHQT_EXPORT ViewerWidget : public osgQt::GLWidget
{
public:
/**
* Constructs a new ViewerWidget, creating an underlying viewer.
* @param[in ] scene Scene graph to attach to the viewer (optional)
*/
explicit ViewerWidget(osg::Node* scene = 0);
/**
* Constructs a new ViewerWidget, attaching an existing viewer.
* @param[in ] viewer Viewer to attach to this widget. The widget will install
* a new camera in the viewer. (NOTE: this widget does not take
* ownership of the Viewer. You are still respsonsile for its
* destruction)
*/
explicit ViewerWidget(osgViewer::ViewerBase* viewer);
/**
* Access the underlying viewer.
*/
osgViewer::ViewerBase* getViewer() { return _viewer.get(); }
/**
* Populates the incoming collection with the views comprising this viewer.
*/
template<typename T>
void getViews( T& views ) const {
osgViewer::ViewerBase::Views temp;
_viewer->getViews(temp);
views.insert(views.end(), temp.begin(), temp.end());
}
virtual ~ViewerWidget();
protected:
QTimer _timer;
void createViewer();
void reconfigure( osgViewer::View* );
void installFrameTimer();
void paintEvent( QPaintEvent* );
osg::observer_ptr<osgViewer::ViewerBase> _viewer;
osg::ref_ptr<osg::GraphicsContext> _gc;
};
} }
#endif // OSGEARTHQT_VIEWERWIDGET_H

View File

@ -1,167 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
* Copyright 2008-2012 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
//#include <osgEarthQt/ViewerWidget>
#include "ViewerWidget"
#include <osgEarthUtil/EarthManipulator>
#include <osgGA/StateSetManipulator>
#include <osgQt/GraphicsWindowQt>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <QtGui>
#include <QtCore/QTimer>
#include <QtGui/QWidget>
using namespace osgEarth;
using namespace osgEarth::QtGui;
ViewerWidget::ViewerWidget(osg::Node* scene)
{
// create a new viewer (a simple osgViewer::Viewer)
createViewer();
// attach the scene graph provided by the user
if (scene)
{
dynamic_cast<osgViewer::Viewer*>(_viewer.get())->setSceneData( scene );
}
// start up the paint event timer.
installFrameTimer();
}
ViewerWidget::ViewerWidget(osgViewer::ViewerBase* viewer) :
_viewer( viewer )
{
if ( !_viewer.valid() )
{
// create a viewer if the user passed in NULL
createViewer();
}
else
{
// reconfigure all the viewer's views to use a Qt graphics context.
osgViewer::ViewerBase::Views views;
getViews( views );
for( osgViewer::ViewerBase::Views::iterator v = views.begin(); v != views.end(); ++v )
{
reconfigure( *v );
}
// disable event setting on the viewer.
viewer->setKeyEventSetsDone(0);
viewer->setQuitEventSetsDone(false);
}
// start up the paint event timer.
installFrameTimer();
}
ViewerWidget::~ViewerWidget()
{
_timer.stop();
if ( _viewer.valid() )
{
_viewer->stopThreading();
_viewer = 0L;
}
OE_DEBUG << "ViewerWidget::DTOR" << std::endl;
}
void ViewerWidget::installFrameTimer()
{
// start the frame timer.
connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
_timer.start(15);
}
void ViewerWidget::createViewer()
{
// creates a simple basic viewer.
osgViewer::Viewer* viewer = new osgViewer::Viewer();
viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
viewer->setCameraManipulator(new osgEarth::Util::EarthManipulator());
viewer->addEventHandler(new osgViewer::StatsHandler());
viewer->addEventHandler(new osgGA::StateSetManipulator());
viewer->addEventHandler(new osgViewer::ThreadingHandler());
viewer->setKeyEventSetsDone(0);
viewer->setQuitEventSetsDone(false);
reconfigure( viewer );
_viewer = viewer;
}
void ViewerWidget::reconfigure( osgViewer::View* view )
{
if ( !_gc.valid() )
{
// create the Qt graphics context if necessary; it will be shared across all views.
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits(ds);
traits->readDISPLAY();
if (traits->displayNum<0) traits->displayNum = 0;
traits->windowName = "osgEarthViewerQt";
traits->windowDecoration = false;
traits->x = x();
traits->y = y();
traits->width = width();
traits->height = height();
traits->doubleBuffer = true;
traits->inheritedWindowData = new osgQt::GraphicsWindowQt::WindowData(this);
_gc = new osgQt::GraphicsWindowQt( traits.get() );
}
// reconfigure this view's camera to use the Qt GC if necessary.
osg::Camera* camera = view->getCamera();
if ( camera->getGraphicsContext() != _gc.get() )
{
camera->setGraphicsContext( _gc.get() );
if ( !camera->getViewport() )
{
camera->setViewport(new osg::Viewport(0, 0, _gc->getTraits()->width, _gc->getTraits()->height));
}
camera->setProjectionMatrixAsPerspective(
30.0f, camera->getViewport()->width()/camera->getViewport()->height(), 1.0f, 10000.0f );
}
}
void ViewerWidget::paintEvent(QPaintEvent* e)
{
Q_UNUSED( e );
if (_viewer->getRunFrameScheme() == osgViewer::ViewerBase::CONTINUOUS ||
_viewer->checkNeedToDoFrame() )
{
_viewer->frame();
}
}

View File

@ -1,693 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
* Copyright 2008-2010 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTHUTIL_CONTROLS
#define OSGEARTHUTIL_CONTROLS
#define HAVE_OSGEARTH_CHILD_SPACING 1
#include <osgEarthUtil/Common>
#include <osgEarth/Common>
#include <osg/Drawable>
#include <osg/Geode>
#include <osg/MatrixTransform>
#include <osg/MixinVector>
#include <osgGA/GUIEventHandler>
#include <osgViewer/View>
#include <osgText/Font>
#include <osgText/Text>
#include <vector>
#include <queue>
#include <qglobal.h>
#undef OSGEARTHUTIL_EXPORT
#define OSGEARTHUTIL_EXPORT
/**
* Controls - A simple 2D UI toolkit.
*
* Controls are 2D interface components that automatically layout to fit their containers.
* The support layout containers, margins and padding, alignment/justification, and docking.
* Controls are a quick and easy way to add "HUD" components to a scene. Just create a
* ControlSurface and add it to a View's scene. Then create and add Controls to that
* surface.
*/
namespace osgEarth { namespace Util { namespace Controls21
{
using namespace osgEarth;
typedef std::vector< osg::ref_ptr<osg::Drawable> > DrawableList;
typedef std::map< class Control*, osg::Geode* > GeodeTable;
// holds 4-sided gutter dimensions (for margins and padding) .. no-export, header-only.
struct Gutter
{
Gutter()
: _top(0), _right(0), _bottom(0), _left(0) { }
Gutter( float top, float right, float bottom, float left )
: _top(top), _right(right), _bottom(bottom), _left(left) { }
Gutter( float y, float x )
: _top(y), _right(x), _bottom(y), _left(x) { }
explicit Gutter( float all )
: _top(all), _right(all), _bottom(all), _left(all) { }
bool operator !=( const Gutter& rhs ) const {
return top() != rhs.top() || right() != rhs.right() || bottom() != rhs.bottom() || left() != rhs.left(); }
float top() const { return _top; }
float left() const { return _left; }
float right() const { return _right; }
float bottom() const { return _bottom; }
float x() const { return _left + _right; }
float y() const { return _top + _bottom; }
osg::Vec2f size() const { return osg::Vec2f(x(), y()); }
osg::Vec2f offset() const { return osg::Vec2f( _left, _top ); }
private:
float _top, _right, _bottom, _left;
};
// internal state class
struct ControlContext
{
ControlContext() : _viewContextID(~0), _view(0), _frameStamp(0) { }
osg::View* _view;
osg::ref_ptr<const osg::Viewport> _vp;
unsigned int _viewContextID;
std::queue< osg::ref_ptr<class Control> > _active;
const osg::FrameStamp* _frameStamp;
};
// base class for control events
class ControlEventHandler : public osg::Referenced
{
public:
/** Click event. */
virtual void onClick( class Control* control ) { Q_UNUSED(control); }
/** Click event with mouse button mask (see osgGA::GUIEventAdapter::MouseButtonMask) */
virtual void onClick( class Control* control, int mouseButtonMask ) { Q_UNUSED( mouseButtonMask ); onClick(control); }
/** Click event with click position (negative values mean you're in the left/top padding) */
virtual void onClick( class Control* control, const osg::Vec2f& pos, int mouseButtonMask ) { Q_UNUSED( pos); onClick(control, mouseButtonMask); }
/** Value events */
virtual void onValueChanged( class Control* control, bool value ) { Q_UNUSED( control ); Q_UNUSED( value ); }
virtual void onValueChanged( class Control* control, double value ) { Q_UNUSED( control ); Q_UNUSED( value );}
virtual void onValueChanged( class Control* control, float value ) { Q_UNUSED( control ); Q_UNUSED( value );}
virtual void onValueChanged( class Control* control, int value ) { Q_UNUSED( control ); Q_UNUSED( value ); }
virtual void onValueChanged( class Control* control, const osg::Vec3f& value ) { Q_UNUSED( control ); Q_UNUSED( value ); }
virtual void onValueChanged( class Control* control, const osg::Vec2f& value ) { Q_UNUSED( control ); Q_UNUSED( value ); }
virtual void onValueChanged( class Control* control, const osg::Vec3d& value ) { Q_UNUSED( control ); Q_UNUSED( value ); }
virtual void onValueChanged( class Control* control, const osg::Vec2d& value ) { Q_UNUSED( control ); Q_UNUSED( value ); }
virtual void onValueChanged( class Control* control, const std::string& value ) { Q_UNUSED( control ); Q_UNUSED( value ); }
virtual void onValueChanged( class Control* control, void* value ) { Q_UNUSED( control ); Q_UNUSED( value ); }
};
typedef std::list< osg::ref_ptr<ControlEventHandler> > ControlEventHandlerList;
/**
* Base class for all controls. You can actually use a Control directly and it
* will just render as a rectangle.
*/
class OSGEARTHUTIL_EXPORT Control : public osg::Referenced
{
public:
enum Alignment
{
ALIGN_NONE, ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_TOP, ALIGN_BOTTOM
};
enum Dock
{
DOCK_NONE, DOCK_LEFT, DOCK_RIGHT, DOCK_TOP, DOCK_BOTTOM, DOCK_FILL
};
public:
Control();
void setX( float value );
const osgEarth::optional<float>& x() const { return _x; }
void clearX() { _x.unset(); dirty(); }
void setY( float value );
const osgEarth::optional<float>& y() const { return _y; }
void clearY() { _y.unset(); dirty(); }
void setPosition( float x, float y );
void setWidth( float value );
const osgEarth::optional<float>& width() const { return _width; }
void clearWidth() { _width.unset(); dirty(); }
void setHeight( float value );
const osgEarth::optional<float>& height() const { return _height; }
void clearHeight() { _height.unset(); dirty(); }
void setSize( float w, float h );
void setMargin( const Gutter& value );
const Gutter& margin() const { return _margin; }
// space between container and its content
void setPadding( const Gutter& value );
void setPadding( float globalValue );
const Gutter& padding() const { return _padding; }
void setVertAlign( const Alignment& value );
const optional<Alignment>& vertAlign() const { return _valign; }
void setHorizAlign( const Alignment& value );
const optional<Alignment>& horizAlign() const { return _halign; }
void setHorizFill( bool value, float minWidth =0.0f );
bool horizFill() const { return _hfill; }
void setVertFill( bool value, float minHeight =0.0f );
bool vertFill() const { return _vfill; }
void setVisible( bool value );
bool visible() const { return _visible; }
void setForeColor( const osg::Vec4f& value );
void setForeColor( float r, float g, float b, float a ) { setForeColor( osg::Vec4f(r,g,b,a) ); }
const osgEarth::optional<osg::Vec4f> foreColor() const { return _foreColor; }
void clearForeColor() { _foreColor.unset(); dirty(); }
void setBackColor( const osg::Vec4f& value );
void setBackColor( float r, float g, float b, float a ) { setBackColor( osg::Vec4f(r,g,b,a) ); }
const osgEarth::optional<osg::Vec4f>& backColor() const { return _backColor; }
void clearBackColor() { _backColor.unset(); dirty(); }
void setActiveColor( const osg::Vec4f& value );
void setActiveColor( float r, float g, float b, float a ) { setActiveColor( osg::Vec4f(r,g,b,a) ); }
const osgEarth::optional<osg::Vec4f>& activeColor() const { return _activeColor; }
void clearActiveColor() { _activeColor.unset(); dirty(); }
bool getParent( osg::ref_ptr<Control>& out ) const;
void setActive( bool value );
bool getActive() const { return _active; }
void setAbsorbEvents( bool value ) { _absorbEvents = value; }
bool getAbsorbEvents() const { return _absorbEvents; }
void addEventHandler( ControlEventHandler* handler );
public:
// mark the control as dirty so that it will regenerate on the next pass.
virtual void dirty();
bool isDirty() const { return _dirty; }
virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
virtual void calcFill( const ControlContext& context ) { Q_UNUSED( context ); }
virtual void calcPos ( const ControlContext& context, const osg::Vec2f& cursor, const osg::Vec2f& parentSize );
virtual void draw ( const ControlContext& context, DrawableList& out_drawables );
// actual rendering region on the control surface
const osg::Vec2f& renderPos() const { return _renderPos; }
const osg::Vec2f& renderSize() const { return _renderSize; }
// does the control contain the point?
bool intersects( float x, float y ) const;
void setParent( class Control* c ) { _parent = c; }
protected:
bool _dirty;
osg::Vec2f _renderPos; // rendering position (includes padding offset)
osg::Vec2f _renderSize; // rendering size (includes padding)
// adjusts renderpos for alignment.
void align();
friend class ControlCanvas;
friend class Container;
virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, ControlContext& cx );
ControlEventHandlerList _eventHandlers;
private:
osgEarth::optional<float> _x, _y, _width, _height;
Gutter _margin;
Gutter _padding;
bool _visible;
optional<Alignment> _valign, _halign;
optional<osg::Vec4f> _backColor, _foreColor, _activeColor;
bool _active;
bool _absorbEvents;
bool _hfill, _vfill;
osg::observer_ptr<Control> _parent;
osg::ref_ptr<osg::Geometry> _geom;
};
typedef std::vector< osg::ref_ptr<Control> > ControlVector;
/**
* Control that contains a raster image
*/
class OSGEARTHUTIL_EXPORT ImageControl : public Control
{
public:
explicit ImageControl( osg::Image* image =0L );
void setImage( osg::Image* image );
osg::Image* getImage() const { return _image.get(); }
/** Rotates the image. */
void setRotation( float rotation_deg );
float getRotation() const { return osg::RadiansToDegrees(_rotation_rad); }
/** Tells the control to fix its minimum size to account to rotation. Otherwise the
control will auto-size its width/height based on the rotation angle. */
void setFixSizeForRotation( bool value );
bool getFixSizeForRotation() const { return _fixSizeForRot; }
public: // Control
virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
virtual void draw( const ControlContext& cx, DrawableList& out );
private:
osg::ref_ptr<osg::Image> _image;
float _rotation_rad;
bool _fixSizeForRot;
};
/**
* A control that provides a horizontal sliding value controller.
*/
class OSGEARTHUTIL_EXPORT HSliderControl : public Control
{
public:
HSliderControl( float min = 0.0f, float max = 100.0f, float value = 50.0f );
void setMin( float min, bool notify =true );
float getMin() const { return _min; }
void setMax( float max, bool notify =true );
float getMax() const { return _max; }
void setValue( float value, bool notify =true );
float getValue() const { return _value; }
public: // Control
//virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
virtual void draw( const ControlContext& cx, DrawableList& out );
protected:
virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, ControlContext& cx );
void fireValueChanged();
private:
float _min, _max, _value;
};
/**
* A check box toggle.
*/
class OSGEARTHUTIL_EXPORT CheckBoxControl : public Control
{
public:
explicit CheckBoxControl( bool checked = false );
CheckBoxControl( bool checked, ControlEventHandler* callback );
void setValue( bool value );
bool getValue() const { return _value; }
public:
virtual void draw( const ControlContext& cx, DrawableList& out );
protected:
virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, ControlContext& cx );
void fireValueChanged();
private:
bool _value;
};
typedef std::vector< osg::ref_ptr<Control> > ControlList;
/**
* A control that renders a simple rectangular border for a container.
* This is also the base class for all Frame objects.
*/
class OSGEARTHUTIL_EXPORT Frame : public ImageControl
{
public:
Frame();
public: // Control
virtual void calcPos ( const ControlContext& context, const osg::Vec2f& cursor, const osg::Vec2f& parentSize );
virtual void draw( const ControlContext& context, DrawableList& drawables );
};
/**
* A Frame with nice rounded corners.
*/
class OSGEARTHUTIL_EXPORT RoundedFrame : public Frame
{
public:
RoundedFrame();
public:
virtual void draw( const ControlContext& cx, DrawableList& drawables );
};
/**
* Container is a control that houses child controls. This is the base class for
* all containers. (It is abstract so cannot be used directly)
* Containers are control, so you can nest them in other containers.
*/
class OSGEARTHUTIL_EXPORT Container : public Control
{
public:
Container();
// the Frame connected to this container. can be NULL for no frame.
void setFrame( Frame* frame );
Frame* getFrame() const { return _frame.get(); }
// space between children
void setChildSpacing( float value );
float childSpacing() const { return _spacing; }
// horiz alignment to set on children (that do not already have alignment explicity set)
void setChildHorizAlign( Alignment align );
const optional<Alignment>& childHorizAlign() const { return _childhalign; }
// vert alignment to set on children (that do not already have alignment explicity set)
void setChildVertAlign( Alignment align );
const optional<Alignment>& childVertAlign() const { return _childvalign; }
// default add function.
virtual void addControl( Control* control, int index =-1 ) =0;
// default multiple-add function.
virtual void addControls( const ControlVector& controls );
// access to the child list.
virtual const ControlList& children() const =0;
// clear the controls list.
virtual void clearControls() =0;
public:
virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
virtual void calcFill( const ControlContext& context );
virtual void calcPos ( const ControlContext& context, const osg::Vec2f& cursor, const osg::Vec2f& parentSize );
virtual void draw( const ControlContext& context, DrawableList& drawables );
protected:
virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, ControlContext& cx );
void applyChildAligns();
//void setChildRenderSize( Control* child, float w, float h ) { child->_renderSize.set( w, h ); }
float& renderWidth(Control* child) { return child->_renderSize.x(); }
float& renderHeight(Control* child) { return child->_renderSize.y(); }
private:
osg::ref_ptr<Frame> _frame;
float _spacing;
optional<Alignment> _childhalign;
optional<Alignment> _childvalign;
ControlList& mutable_children() { return const_cast<ControlList&>(children()); }
};
/**
* Container that stacks controls vertically.
*/
class OSGEARTHUTIL_EXPORT VBox : public Container
{
public:
VBox();
public: // Container
virtual void addControl( Control* control, int index =-1 );
virtual const ControlList& children() const { return _controls; }
virtual void clearControls();
public: // Control
virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
virtual void calcFill( const ControlContext& context );
virtual void calcPos ( const ControlContext& context, const osg::Vec2f& cursor, const osg::Vec2f& parentSize );
virtual void draw( const ControlContext& context, DrawableList& drawables );
private:
ControlList _controls;
};
/**
* Container that stacks controls horizontally.
*/
class OSGEARTHUTIL_EXPORT HBox : public Container
{
public:
HBox();
public: // Container
virtual void addControl( Control* control, int index =-1 );
virtual const ControlList& children() const { return _controls; }
virtual void clearControls();
public: // Control
virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
virtual void calcFill( const ControlContext& context );
virtual void calcPos ( const ControlContext& context, const osg::Vec2f& cursor, const osg::Vec2f& parentSize );
virtual void draw( const ControlContext& context, DrawableList& drawables );
private:
ControlList _controls;
};
/**
* Container that organizes its children in a grid.
*/
class OSGEARTHUTIL_EXPORT Grid : public Container
{
public:
Grid();
void setControl( int col, int row, Control* control );
unsigned getNumRows() const { return _rows.size(); }
unsigned getNumColumns() const { return _colWidths.size(); }
public: // Container
virtual void addControl( Control* control, int index =-1 );
virtual const ControlList& children() const { return _children; }
virtual void clearControls();
// adds the controls as a row at the bottom of the grid.
virtual void addControls( const ControlVector& controls );
public: // Control
virtual void calcSize( const ControlContext& context, osg::Vec2f& out_size );
virtual void calcFill( const ControlContext& context );
virtual void calcPos ( const ControlContext& context, const osg::Vec2f& cursor, const osg::Vec2f& parentSize );
virtual void draw( const ControlContext& context, DrawableList& drawables );
private:
typedef std::vector< osg::ref_ptr<Control> > Row;
typedef std::vector< Row > RowVector;
RowVector _rows;
ControlList _children;
osg::ref_ptr<Control>& cell(int col, int row);
void expandToInclude(int cols, int rows);
std::vector<float> _rowHeights, _colWidths;
};
class OSGEARTHUTIL_EXPORT RefNodeVector :
public osg::Referenced,
public osg::MixinVector<osg::Node*> { };
/**
* A control wrapped in a node that you can place anywhere in the scene
* graph. Its scene location will control its 2D screen position, and it
* can participate in conflict resolution.
*/
class OSGEARTHUTIL_EXPORT ControlNode : public osg::Node
{
public:
/** Constructs a new control node with an embedded control. */
ControlNode( Control* control, float priority =0.0f );
/** The control encaspulated in this node */
Control* getControl() const { return _control.get(); }
/** The draw priority of this control */
float getPriority() const { return _priority; }
/** The point (in screen-space, relative to the lower-left of the control) that should anchor to the scene */
optional<osg::Vec2f>& anchorPoint() { return _anchor; }
const optional<osg::Vec2f>& anchorPoint() const { return _anchor; }
public: // osg::Node overrides
virtual void traverse( osg::NodeVisitor& nv );
virtual osg::BoundingSphere computeBound() const;
protected:
struct PerViewData
{
PerViewData();
bool _obscured;
float _visibleTime;
osg::Vec3f _screenPos;
unsigned _visitFrame;
osg::ref_ptr<osg::Uniform> _uniform;
osg::observer_ptr<osg::Camera> _canvas;
};
typedef std::map<osg::View*,PerViewData> PerViewDataMap;
PerViewDataMap _perViewData;
osg::ref_ptr<Control> _control;
float _priority;
optional<osg::Vec2f> _anchor;
PerViewData& getData( osg::View* view ) { return _perViewData[view]; }
friend class ControlNodeBin;
};
/**
* Internal class that renders ControlNode objects found in the scene graph.
* There is no need to instantiate or access this object directly.
*/
class OSGEARTHUTIL_EXPORT ControlNodeBin : public osg::Group
{
public:
ControlNodeBin();
/** Registers a control node with this bin. */
void addNode( ControlNode* node );
/** Whether to fade-in controls when they appear in view (default=true) */
void setFading( bool value );
private:
typedef std::pair<float, osg::ref_ptr<ControlNode> > ControlNodePair;
typedef std::multimap<float, osg::ref_ptr<ControlNode> > ControlNodeCollection;
ControlNodeCollection _controlNodes;
typedef std::pair<Control*, ControlNodeCollection::iterator> ControlIndexPair;
typedef std::map<Control*, ControlNodeCollection::iterator> ControlIndex;
ControlIndex _index;
typedef std::map<ControlNode*, osg::MatrixTransform*> RenderNodeTable;
typedef std::pair<ControlNode*, osg::MatrixTransform*> RenderNodePair;
RenderNodeTable _renderNodes;
osg::ref_ptr<osg::Group> _group;
std::vector<osg::BoundingBox> _taken;
bool _sortingEnabled;
bool _sortByDistance;
bool _fading;
friend class ControlCanvas;
friend class ControlNode;
void draw( const ControlContext& context, bool newContext, int bin );
osg::Group* getControlGroup() const { return _group.get(); }
};
/**
* Associates controls with an OSG View.
*/
class OSGEARTHUTIL_EXPORT ControlCanvas : public osg::Camera
{
public:
/** Accesses the control canvas attached the the specified view. */
static ControlCanvas* get( osg::View* view, bool installCanvasInSceneData =false );
public:
/** adds a top-level control to this surface. */
void addControl( Control* control );
/** removes a top-level control. */
void removeControl( Control* control );
/** gets the top-most control that intersects the specified position. */
Control* getControlAtMouse( float x, float y ) const;
/** Toggles whether ControlNodes are allowed to overlap. */
void setAllowControlNodeOverlap( bool value );
public:
// internal- no need to call directly
void update( const osg::FrameStamp* frameStamp );
// internal - no need to call directly
void setControlContext( const ControlContext& );
public:
virtual void traverse( osg::NodeVisitor& nv ); // override
virtual ~ControlCanvas();
/**
* Constructs a new canvas and attaches it to a view. Call
* getOrCreateControlCanvas(view) to create one.
*/
explicit ControlCanvas( osgViewer::View* view );
protected:
ControlList _controls;
GeodeTable _geodeTable;
ControlContext _context;
bool _contextDirty;
osg::ref_ptr<ControlNodeBin> _controlNodeBin;
private:
friend struct ControlCanvasEventHandler;
friend class ControlNode;
ControlCanvas( osgViewer::View* view, bool registerCanvas );
void init( osgViewer::View* view, bool registerCanvas );
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa );
// a static registry of canvases in the scene graph.
typedef std::map<osg::View*, ControlCanvas*> ViewCanvasMap;
static ViewCanvasMap _viewCanvasMap;
static OpenThreads::Mutex _viewCanvasMapMutex;
/** Accesses the priority rendering bin for this canvas. */
ControlNodeBin* getControlNodeBin() { return _controlNodeBin.get(); }
};
} } } // namespace osgEarth::Util::Controls
#endif // OSGEARTHUTIL_CONTROLS

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
SET (PYTHON_OUTPUT_DIRECTORY ${QGIS_OUTPUT_DIRECTORY}/python)
SET (QGIS_GLOBE_PYTHON_OUTPUT_DIRECTORY ${PYTHON_OUTPUT_DIRECTORY}/qgis)
SET (QGIS_GLOBE_PYTHON_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
SET (QGIS_GLOBE_INCLUDE_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/..)
INCLUDE_DIRECTORIES(
${PYTHON_INCLUDE_PATH}
${SIP_INCLUDE_DIR}
..
../../../core
)
IF(WIN32)
IF(MSVC)
ADD_DEFINITIONS("-DGLOBE_EXPORT=${DLLIMPORT}")
ENDIF(MSVC)
ENDIF(WIN32)
SET(SIP_INCLUDES ${SIP_INCLUDES} ${QGIS_GLOBE_PYTHON_DIRECTORY})
SET(SIP_DISABLE_FEATURES ${SIP_DISABLE_FEATURES} QSETINT_CONVERSION)
SET(SIP_DISABLE_FEATURES ${SIP_DISABLE_FEATURES} QSETTYPE_CONVERSION)
SET(SIP_DISABLE_FEATURES ${SIP_DISABLE_FEATURES} QVECTORINT_CONVERSION)
IF(NOT ENABLE_QT5)
SET(SIP_DISABLE_FEATURES ${SIP_DISABLE_FEATURES} QT5_SUPPORT)
ENDIF(NOT ENABLE_QT5)
# globe module
SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${QGIS_GLOBE_PYTHON_OUTPUT_DIRECTORY})
SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${QGIS_GLOBE_PYTHON_OUTPUT_DIRECTORY})
FILE(GLOB_RECURSE sip_files_globe *.sip)
SET(SIP_EXTRA_FILES_DEPEND ${sip_files_globe})
SET(SIP_EXTRA_OPTIONS ${PYQT_SIP_FLAGS} -o -a ${CMAKE_BINARY_DIR}/python/qgis.globe.api)
GENERATE_SIP_PYTHON_MODULE_CODE(qgis.globe globe.sip cpp_files)
BUILD_SIP_PYTHON_MODULE(qgis.globe globe.sip ${cpp_files} "" globeplugin)

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
__init__.py
---------------------
Date : Aug 2013
Copyright : (C) 2013 by Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Matthias Kuhn'
__date__ = 'August 2013'
__copyright__ = '(C) 2013, Matthias Kuhn'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

View File

@ -0,0 +1,22 @@
%Import QtCore/QtCoremod.sip
%Import QtGui/QtGuimod.sip
%Import gui/gui.sip
%Import core/core.sip
//%Import osgEarth/Symbology/Symbology.sip
//%Import osgEarth/Features/Features.sip
%Import osg/osg/osg.sip
%Import osg/osgViewer/osgViewer.sip
%Module(name=qgis.globe,
version=0,
keyword_arguments="Optional")
%If(WS_WIN)
typedef void XEvent;
%End
//%Include qgsglobefeatureutils.sip
%Include qgsglobeinterface.sip

View File

@ -0,0 +1,16 @@
class QgsGlobeFeatureUtils
{
%TypeHeaderCode
#include <qgsglobefeatureutils.h>
%End
public:
static inline QgsPointV2 qgsPointFromPoint( const osg::Vec3d& pt );
static inline osg::Vec3d pointFromQgsPoint( const QgsPointV2& pt );
static inline osgEarth::Features::LineString* lineStringFromQgsLineString( const QgsLineStringV2* lineString );
static inline osgEarth::Features::Polygon* polygonFromQgsPolygon( const QgsPolygonV2* polygon );
static inline osgEarth::Features::Geometry* geometryFromQgsGeometry( const QgsGeometry& geom );
static osgEarth::Features::Feature* featureFromQgsFeature( QgsVectorLayer* layer, QgsFeature& feat );
static void setFeatureField( osgEarth::Features::Feature* feature, const QgsField& field, const QVariant& value );
static osgEarth::Features::FeatureSchema schemaForFields( const QgsFields& fields );
};

View File

@ -0,0 +1,44 @@
/***************************************************************************
qgsglobeinterface.sip
--------------------------------------
Date : 22.8.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
class QgsGlobeInterface : QObject
{
%TypeHeaderCode
#include "qgsglobeinterface.h"
%End
// Provide converter code
// Attention: qgis.globe has to be imported before this interface
// is requested the first time. In case this is not done,
// the converter code will not be executed and this will be treated as
// a (useless) QgsPluginInterface object instead.
%ConvertToSubClassCode
if ( sipCpp->inherits( sipName_QgsGlobeInterface ) )
sipType = sipType_QgsGlobeInterface;
else
sipType = NULL;
%End
public:
osgViewer::Viewer* osgViewer();
// osgEarth::MapNode* mapNode();
void syncExtent();
void enableFrustumHighlight( bool status );
void enableFeatureIdentification( bool status );
private:
// Instances will only be created from the globe plugin itself
QgsGlobeInterface();
};

View File

@ -0,0 +1,85 @@
/***************************************************************************
qgsglobefeatureidentify.cpp
--------------------------------------
Date : 27.10.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsglobefeatureidentify.h"
#include "qgsmapcanvas.h"
#include "featuresource/qgsglobefeaturesource.h"
#include <qgsmaplayerregistry.h>
#include <qgsrubberband.h>
#include <qgsvectorlayer.h>
#include <osg/ValueObject>
#include <osgEarth/Registry>
QgsGlobeFeatureIdentifyCallback::QgsGlobeFeatureIdentifyCallback( QgsMapCanvas* mapCanvas )
: mCanvas( mapCanvas ), mRubberBand( new QgsRubberBand( mapCanvas, QGis::Polygon ) )
{
QColor color( Qt::green );
color.setAlpha( 190 );
mRubberBand->setColor( color );
}
QgsGlobeFeatureIdentifyCallback::~QgsGlobeFeatureIdentifyCallback()
{
mCanvas->scene()->removeItem( mRubberBand );
delete mRubberBand;
}
#if OSGEARTH_VERSION_LESS_THAN(2, 7, 0)
void QgsGlobeFeatureIdentifyCallback::onHit( osgEarth::Features::FeatureSourceIndexNode* index, osgEarth::Features::FeatureID fid, const EventArgs& /*args*/ )
{
QgsGlobeFeatureSource* globeSource = dynamic_cast<QgsGlobeFeatureSource*>( index->getFeatureSource() );
if ( globeSource )
{
QgsVectorLayer* lyr = globeSource->layer();
#else
void QgsGlobeFeatureIdentifyCallback::onHit( osgEarth::ObjectID id )
{
osgEarth::Features::FeatureIndex* index = osgEarth::Registry::objectIndex()->get<osgEarth::Features::FeatureIndex>( id );
osgEarth::Features::Feature* feature = index->getFeature( id );
osgEarth::Features::FeatureID fid = feature->getFID();
std::string layerId;
if ( feature->getUserValue( "qgisLayerId", layerId ) )
{
QgsVectorLayer* lyr = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( QString::fromStdString( layerId ) ) );
#endif
if ( lyr )
{
QgsFeature feat;
lyr->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( feat );
if ( feat.isValid() )
mRubberBand->setToGeometry( feat.geometry(), lyr );
else
mRubberBand->reset( QGis::Polygon );
}
}
else
{
QgsDebugMsg( "Clicked feature was not on a QGIS layer" );
}
}
#if OSGEARTH_VERSION_LESS_THAN(2, 7, 0)
void QgsGlobeFeatureIdentifyCallback::onMiss( const EventArgs &/*args*/ )
#else
void QgsGlobeFeatureIdentifyCallback::onMiss()
#endif
{
mRubberBand->reset( QGis::Polygon );
}

View File

@ -0,0 +1,48 @@
/***************************************************************************
qgsglobefeatureidentify.h
--------------------------------------
Date : 27.10.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGLOBEFEATUREIDENTIFY_H
#define QGSGLOBEFEATUREIDENTIFY_H
#include <osgEarth/Version>
#include <osgEarthUtil/FeatureQueryTool>
class QgsMapCanvas;
class QgsRubberBand;
#if OSGEARTH_VERSION_LESS_THAN(2, 7, 0)
class QgsGlobeFeatureIdentifyCallback : public osgEarth::Util::FeatureQueryTool::Callback
#else
class QgsGlobeFeatureIdentifyCallback : public osgEarth::Picker::Callback
#endif
{
public:
QgsGlobeFeatureIdentifyCallback( QgsMapCanvas* mapCanvas );
~QgsGlobeFeatureIdentifyCallback();
#if OSGEARTH_VERSION_LESS_THAN(2, 7, 0)
void onHit( osgEarth::Features::FeatureSourceIndexNode* index, osgEarth::Features::FeatureID fid, const EventArgs& args ) override;
void onMiss( const EventArgs &args ) override;
#else
void onHit( osgEarth::ObjectID id ) override;
void onMiss() override;
#endif
private:
QgsMapCanvas* mCanvas;
QgsRubberBand* mRubberBand;
};
#endif // QGSGLOBEFEATUREIDENTIFY_H

View File

@ -0,0 +1,59 @@
/***************************************************************************
qgsglobefrustumhighlight.cpp
--------------------------------------
Date : 27.10.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <qgsrubberband.h>
#include <qgsmapcanvas.h>
#include <qgsmaprenderer.h>
#include <osg/View>
#include <osgEarth/SpatialReference>
#include <osgEarth/Terrain>
#include "qgsglobefrustumhighlight.h"
QgsGlobeFrustumHighlightCallback::QgsGlobeFrustumHighlightCallback( osg::View* view, osgEarth::Terrain* terrain, QgsMapCanvas* mapCanvas, QColor color )
: osg::NodeCallback()
, mView( view )
, mTerrain( terrain )
, mRubberBand( new QgsRubberBand( mapCanvas, QGis::Polygon ) )
, mSrs( osgEarth::SpatialReference::create( mapCanvas->mapRenderer()->destinationCrs().toWkt().toStdString() ) )
{
mRubberBand->setColor( color );
}
QgsGlobeFrustumHighlightCallback::~QgsGlobeFrustumHighlightCallback()
{
delete mRubberBand;
}
void QgsGlobeFrustumHighlightCallback::operator()( osg::Node*, osg::NodeVisitor* )
{
const osg::Viewport::value_type &width = mView->getCamera()->getViewport()->width();
const osg::Viewport::value_type &height = mView->getCamera()->getViewport()->height();
osg::Vec3d corners[4];
mTerrain->getWorldCoordsUnderMouse( mView, 0, 0, corners[0] );
mTerrain->getWorldCoordsUnderMouse( mView, 0, height - 1, corners[1] );
mTerrain->getWorldCoordsUnderMouse( mView, width - 1, height - 1, corners[2] );
mTerrain->getWorldCoordsUnderMouse( mView, width - 1, 0, corners[3] );
mRubberBand->reset( QGis::Polygon );
for ( int i = 0; i < 4; i++ )
{
osg::Vec3d localCoords;
mSrs->transformFromWorld( corners[i], localCoords );
mRubberBand->addPoint( QgsPoint( localCoords.x(), localCoords.y() ) );
}
}

View File

@ -0,0 +1,44 @@
/***************************************************************************
qgsglobefrustumhighlight.h
--------------------------------------
Date : 27.10.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGLOBEFRUSTUMHIGHLIGHT_H
#define QGSGLOBEFRUSTUMHIGHLIGHT_H
#include <osg/NodeCallback>
class QgsRubberBand;
namespace osg { class View; }
namespace osgEarth
{
class Terrain;
class SpatialReference;
}
struct QgsGlobeFrustumHighlightCallback : public osg::NodeCallback
{
public:
QgsGlobeFrustumHighlightCallback( osg::View* view, osgEarth::Terrain* terrain, QgsMapCanvas* mapCanvas, QColor color );
~QgsGlobeFrustumHighlightCallback();
void operator()( osg::Node*, osg::NodeVisitor* ) override;
private:
osg::View* mView;
osgEarth::Terrain* mTerrain;
QgsRubberBand* mRubberBand;
osgEarth::SpatialReference* mSrs;
};
#endif // QGSGLOBEFRUSTUMHIGHLIGHT_H

View File

@ -0,0 +1,48 @@
/***************************************************************************
qgsglobeinterface.cpp
--------------------------------------
Date : 22.8.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsglobeinterface.h"
#include "globe_plugin.h"
QgsGlobeInterface::QgsGlobeInterface( GlobePlugin* const globe, QObject* parent )
: QgsPluginInterface( parent )
, mGlobe( globe )
{
}
osgViewer::Viewer* QgsGlobeInterface::osgViewer()
{
return mGlobe->osgViewer();
}
osgEarth::MapNode* QgsGlobeInterface::mapNode()
{
return mGlobe->mapNode();
}
void QgsGlobeInterface::syncExtent()
{
mGlobe->syncExtent();
}
void QgsGlobeInterface::enableFrustumHighlight( bool status )
{
mGlobe->enableFrustumHighlight( status );
}
void QgsGlobeInterface::enableFeatureIdentification( bool status )
{
mGlobe->enableFeatureIdentification( status );
}

View File

@ -0,0 +1,46 @@
/***************************************************************************
qgsglobeinterface.h
--------------------------------------
Date : 22.8.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGLOBEINTERFACE_H
#define QGSGLOBEINTERFACE_H
#include <QObject>
#include "qgsplugininterface.h"
class GlobePlugin;
class QDateTime;
namespace osgViewer { class Viewer; }
namespace osgEarth { class MapNode; }
class GLOBE_EXPORT QgsGlobeInterface : public QgsPluginInterface
{
public:
QgsGlobeInterface( GlobePlugin* const globe, QObject* parent = 0 );
osgViewer::Viewer* osgViewer();
osgEarth::MapNode* mapNode();
void syncExtent();
void enableFrustumHighlight( bool status );
void enableFeatureIdentification( bool status );
private:
GlobePlugin* mGlobe;
};
#endif // QGSGLOBEINTERFACE_H

View File

@ -0,0 +1,532 @@
/***************************************************************************
* qgsglobeplugindialog.cpp - settings dialog for the globe plugin
* --------------------------------------
* Date : 11-Nov-2010
* Copyright : (C) 2010 by Marco Bernasocchi
* Email : marco at bernawebdesign.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsglobeplugindialog.h"
#include "globe_plugin.h"
#include <qgsapplication.h>
#include <qgsnetworkaccessmanager.h>
#include <qgsproject.h>
#include <qgslogger.h>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QMenu>
#include <QSettings>
#include <QTimer>
#include <osg/DisplaySettings>
#include <osgViewer/Viewer>
#include <osgEarth/Version>
#include <osgEarthUtil/EarthManipulator>
QgsGlobePluginDialog::QgsGlobePluginDialog( QWidget* parent, Qt::WFlags fl )
: QDialog( parent, fl )
{
setupUi( this );
QMenu* addImageryMenu = new QMenu( this );
QMenu* tmsImageryMenu = new QMenu( this );
tmsImageryMenu->addAction( "Readymap: NASA BlueMarble Imagery", this, SLOT( addTMSImagery() ) )->setData( "http://readymap.org/readymap/tiles/1.0.0/1/" );
tmsImageryMenu->addAction( "Readymap: NASA BlueMarble, ocean only", this, SLOT( addTMSImagery() ) )->setData( "http://readymap.org/readymap/tiles/1.0.0/2/" );
tmsImageryMenu->addAction( "Readymap: High resolution insets from various world locations", this, SLOT( addTMSImagery() ) )->setData( "http://readymap.org/readymap/tiles/1.0.0/3/" );
tmsImageryMenu->addAction( "Readymap: Global Land Cover Facility 15m Landsat", this, SLOT( addTMSImagery() ) )->setData( "http://readymap.org/readymap/tiles/1.0.0/6/" );
tmsImageryMenu->addAction( "Readymap: NASA BlueMarble + Landsat + Ocean Masking Layer", this, SLOT( addTMSImagery() ) )->setData( "http://readymap.org/readymap/tiles/1.0.0/7/" );
tmsImageryMenu->addAction( tr( "Custom..." ), this, SLOT( addCustomTMSImagery() ) );
addImageryMenu->addAction( tr( "TMS" ) )->setMenu( tmsImageryMenu );
QMenu* wmsImageryMenu = new QMenu( this );
wmsImageryMenu->addAction( tr( "Custom..." ), this, SLOT( addCustomWMSImagery() ) );
addImageryMenu->addAction( tr( "WMS" ) )->setMenu( wmsImageryMenu );
QMenu* fileImageryMenu = new QMenu( this );
// fileImageryMenu->addAction("world.tif", this, SLOT(addRasterImagery()));
fileImageryMenu->addAction( tr( "Custom..." ), this, SLOT( addCustomRasterImagery() ) );
addImageryMenu->addAction( tr( "Raster" ) )->setMenu( fileImageryMenu );
mAddImageryButton->setMenu( addImageryMenu );
QMenu* addElevationMenu = new QMenu( this );
QMenu* tmsElevationMenu = new QMenu( this );
tmsElevationMenu->addAction( "Readymap: SRTM 90m Elevation Data", this, SLOT( addTMSElevation() ) )->setData( "http://readymap.org/readymap/tiles/1.0.0/9/" );
tmsElevationMenu->addAction( tr( "Custom..." ), this, SLOT( addCustomTMSElevation() ) );
addElevationMenu->addAction( tr( "TMS" ) )->setMenu( tmsElevationMenu );
QMenu* fileElevationMenu = new QMenu( this );
fileElevationMenu->addAction( tr( "Custom..." ), this, SLOT( addCustomRasterElevation() ) );
addElevationMenu->addAction( tr( "Raster" ) )->setMenu( fileElevationMenu );
mAddElevationButton->setMenu( addElevationMenu );
comboBoxStereoMode->addItem( "OFF", -1 );
comboBoxStereoMode->addItem( "ANAGLYPHIC", osg::DisplaySettings::ANAGLYPHIC );
comboBoxStereoMode->addItem( "QUAD_BUFFER", osg::DisplaySettings::ANAGLYPHIC );
comboBoxStereoMode->addItem( "HORIZONTAL_SPLIT", osg::DisplaySettings::HORIZONTAL_SPLIT );
comboBoxStereoMode->addItem( "VERTICAL_SPLIT", osg::DisplaySettings::VERTICAL_SPLIT );
lineEditAASamples->setValidator( new QIntValidator( lineEditAASamples ) );
#if OSGEARTH_VERSION_LESS_THAN( 2, 5, 0 )
mSpinBoxVerticalScale->setVisible( false );
#endif
connect( checkBoxSkyAutoAmbient, SIGNAL( toggled( bool ) ), horizontalSliderMinAmbient, SLOT( setEnabled( bool ) ) );
connect( buttonBox->button( QDialogButtonBox::Apply ), SIGNAL( clicked( bool ) ), this, SLOT( apply() ) );
restoreSavedSettings();
readProjectSettings();
}
void QgsGlobePluginDialog::restoreSavedSettings()
{
QSettings settings;
// Video settings
comboBoxStereoMode->setCurrentIndex( comboBoxStereoMode->findText( settings.value( "/Plugin-Globe/stereoMode", "OFF" ).toString() ) );
spinBoxStereoScreenDistance->setValue( settings.value( "/Plugin-Globe/spinBoxStereoScreenDistance",
osg::DisplaySettings::instance()->getScreenDistance() ).toDouble() );
spinBoxStereoScreenWidth->setValue( settings.value( "/Plugin-Globe/spinBoxStereoScreenWidth",
osg::DisplaySettings::instance()->getScreenWidth() ).toDouble() );
spinBoxStereoScreenHeight->setValue( settings.value( "/Plugin-Globe/spinBoxStereoScreenHeight",
osg::DisplaySettings::instance()->getScreenHeight() ).toDouble() );
spinBoxStereoEyeSeparation->setValue( settings.value( "/Plugin-Globe/spinBoxStereoEyeSeparation",
osg::DisplaySettings::instance()->getEyeSeparation() ).toDouble() );
spinBoxSplitStereoHorizontalSeparation->setValue( settings.value( "/Plugin-Globe/spinBoxSplitStereoHorizontalSeparation",
osg::DisplaySettings::instance()->getSplitStereoHorizontalSeparation() ).toInt() );
spinBoxSplitStereoVerticalSeparation->setValue( settings.value( "/Plugin-Globe/spinBoxSplitStereoVerticalSeparation",
osg::DisplaySettings::instance()->getSplitStereoVerticalSeparation() ).toInt() );
comboBoxSplitStereoHorizontalEyeMapping->setCurrentIndex( settings.value( "/Plugin-Globe/comboBoxSplitStereoHorizontalEyeMapping",
osg::DisplaySettings::instance()->getSplitStereoHorizontalEyeMapping() ).toInt() );
comboBoxSplitStereoVerticalEyeMapping->setCurrentIndex( settings.value( "/Plugin-Globe/comboBoxSplitStereoVerticalEyeMapping",
osg::DisplaySettings::instance()->getSplitStereoVerticalEyeMapping() ).toInt() );
groupBoxAntiAliasing->setChecked( settings.value( "/Plugin-Globe/anti-aliasing", false ).toBool() );
lineEditAASamples->setText( settings.value( "/Plugin-Globe/anti-aliasing-level", "" ).toString() );
// Advanced
sliderScrollSensitivity->setValue( settings.value( "/Plugin-Globe/scrollSensitivity", 20 ).toInt() );
checkBoxInvertScroll->setChecked( settings.value( "/Plugin-Globe/invertScrollWheel", 0 ).toInt() );
checkBoxFrustumHighlighting->setChecked( settings.value( "/Plugin-Globe/frustum-highlighting", false ).toBool() );
checkBoxFeatureIdentification->setChecked( settings.value( "/Plugin-Globe/feature-identification", false ).toBool() );
}
void QgsGlobePluginDialog::on_buttonBox_accepted()
{
apply();
accept();
}
void QgsGlobePluginDialog::on_buttonBox_rejected()
{
restoreSavedSettings();
readProjectSettings();
reject();
}
void QgsGlobePluginDialog::apply()
{
QSettings settings;
// Video settings
settings.setValue( "/Plugin-Globe/stereoMode", comboBoxStereoMode->currentText() );
settings.setValue( "/Plugin-Globe/stereoScreenDistance", spinBoxStereoScreenDistance->value() );
settings.setValue( "/Plugin-Globe/stereoScreenWidth", spinBoxStereoScreenWidth->value() );
settings.setValue( "/Plugin-Globe/stereoScreenHeight", spinBoxStereoScreenHeight->value() );
settings.setValue( "/Plugin-Globe/stereoEyeSeparation", spinBoxStereoEyeSeparation->value() );
settings.setValue( "/Plugin-Globe/SplitStereoHorizontalSeparation", spinBoxSplitStereoHorizontalSeparation->value() );
settings.setValue( "/Plugin-Globe/SplitStereoVerticalSeparation", spinBoxSplitStereoVerticalSeparation->value() );
settings.setValue( "/Plugin-Globe/SplitStereoHorizontalEyeMapping", comboBoxSplitStereoHorizontalEyeMapping->currentIndex() );
settings.setValue( "/Plugin-Globe/SplitStereoVerticalEyeMapping", comboBoxSplitStereoVerticalEyeMapping->currentIndex() );
settings.setValue( "/Plugin-Globe/anti-aliasing", groupBoxAntiAliasing->isChecked() );
settings.setValue( "/Plugin-Globe/anti-aliasing-level", lineEditAASamples->text() );
// Advanced settings
settings.setValue( "/Plugin-Globe/scrollSensitivity", sliderScrollSensitivity->value() );
settings.setValue( "/Plugin-Globe/invertScrollWheel", checkBoxInvertScroll->checkState() );
settings.setValue( "/Plugin-Globe/frustum-highlighting", checkBoxFrustumHighlighting->isChecked() );
settings.setValue( "/Plugin-Globe/feature-identification", checkBoxFeatureIdentification->isChecked() );
writeProjectSettings();
// Apply stereo settings
int stereoMode = comboBoxStereoMode->itemData( comboBoxStereoMode->currentIndex() ).toInt();
if ( stereoMode == -1 )
{
osg::DisplaySettings::instance()->setStereo( false );
}
else
{
osg::DisplaySettings::instance()->setStereo( true );
osg::DisplaySettings::instance()->setStereoMode(
static_cast<osg::DisplaySettings::StereoMode>( stereoMode ) );
osg::DisplaySettings::instance()->setEyeSeparation( spinBoxStereoEyeSeparation->value() );
osg::DisplaySettings::instance()->setScreenDistance( spinBoxStereoScreenDistance->value() );
osg::DisplaySettings::instance()->setScreenWidth( spinBoxStereoScreenWidth->value() );
osg::DisplaySettings::instance()->setScreenHeight( spinBoxStereoScreenHeight->value() );
osg::DisplaySettings::instance()->setSplitStereoVerticalSeparation(
spinBoxSplitStereoVerticalSeparation->value() );
osg::DisplaySettings::instance()->setSplitStereoVerticalEyeMapping(
static_cast<osg::DisplaySettings::SplitStereoVerticalEyeMapping>(
comboBoxSplitStereoVerticalEyeMapping->currentIndex() ) );
osg::DisplaySettings::instance()->setSplitStereoHorizontalSeparation(
spinBoxSplitStereoHorizontalSeparation->value() );
osg::DisplaySettings::instance()->setSplitStereoHorizontalEyeMapping(
static_cast<osg::DisplaySettings::SplitStereoHorizontalEyeMapping>(
comboBoxSplitStereoHorizontalEyeMapping->currentIndex() ) );
}
emit settingsApplied();
}
void QgsGlobePluginDialog::readProjectSettings()
{
// Imagery settings
mImageryTreeView->clear();
foreach ( const LayerDataSource& ds, getImageryDataSources() )
{
QTreeWidgetItem* item = new QTreeWidgetItem( QStringList() << ds.type << ds.uri );
item->setFlags( item->flags() & ~Qt::ItemIsDropEnabled );
mImageryTreeView->addTopLevelItem( item );
}
mImageryTreeView->resizeColumnToContents( 0 );
// Elevation settings
mElevationTreeView->clear();
foreach ( const LayerDataSource& ds, getElevationDataSources() )
{
QTreeWidgetItem* item = new QTreeWidgetItem( QStringList() << ds.type << ds.uri );
item->setFlags( item->flags() & ~Qt::ItemIsDropEnabled );
mElevationTreeView->addTopLevelItem( item );
}
mElevationTreeView->resizeColumnToContents( 0 );
#if OSGEARTH_VERSION_GREATER_OR_EQUAL( 2, 5, 0 )
mSpinBoxVerticalScale->setValue( QgsProject::instance()->readDoubleEntry( "Globe-Plugin", "/verticalScale", 1 ) );
#endif
// Map settings
groupBoxSky->setChecked( QgsProject::instance()->readBoolEntry( "Globe-Plugin", "/skyEnabled", true ) );
dateTimeEditSky->setDateTime( QDateTime::fromString( QgsProject::instance()->readEntry( "Globe-Plugin", "/skyDateTime", QDateTime::currentDateTime().toString() ) ) );
checkBoxSkyAutoAmbient->setChecked( QgsProject::instance()->readBoolEntry( "Globe-Plugin", "/skyAutoAmbient", true ) );
horizontalSliderMinAmbient->setValue( QgsProject::instance()->readDoubleEntry( "Globe-Plugin", "/skyMinAmbient", 30. ) );
}
void QgsGlobePluginDialog::writeProjectSettings()
{
// Imagery settings
QgsProject::instance()->removeEntry( "Globe-Plugin", "/imageryDatasources/" );
for ( int row = 0, nRows = mImageryTreeView->topLevelItemCount(); row < nRows; ++row )
{
QTreeWidgetItem* item = mImageryTreeView->topLevelItem( row );
QString key = QString( "/imageryDatasources/L%1" ).arg( row );
QgsProject::instance()->writeEntry( "Globe-Plugin", key + "/type", item->text( 0 ) );
QgsProject::instance()->writeEntry( "Globe-Plugin", key + "/uri", item->text( 1 ) );
}
// Elevation settings
QgsProject::instance()->removeEntry( "Globe-Plugin", "/elevationDatasources/" );
for ( int row = 0, nRows = mElevationTreeView->topLevelItemCount(); row < nRows; ++row )
{
QTreeWidgetItem* item = mElevationTreeView->topLevelItem( row );
QString key = QString( "/elevationDatasources/L%1" ).arg( row );
QgsProject::instance()->writeEntry( "Globe-Plugin", key + "/type", item->text( 0 ) );
QgsProject::instance()->writeEntry( "Globe-Plugin", key + "/uri", item->text( 1 ) );
}
#if OSGEARTH_VERSION_GREATER_OR_EQUAL( 2, 5, 0 )
QgsProject::instance()->writeEntry( "Globe-Plugin", "/verticalScale", mSpinBoxVerticalScale->value() );
#endif
// Map settings
QgsProject::instance()->writeEntry( "Globe-Plugin", "/skyEnabled/", groupBoxSky->isChecked() );
QgsProject::instance()->writeEntry( "Globe-Plugin", "/skyDateTime/", dateTimeEditSky->dateTime().toString() );
QgsProject::instance()->writeEntry( "Globe-Plugin", "/skyAutoAmbient/", checkBoxSkyAutoAmbient->isChecked() );
QgsProject::instance()->writeEntry( "Globe-Plugin", "/skyMinAmbient/", horizontalSliderMinAmbient->value() );
}
bool QgsGlobePluginDialog::validateRemoteUri( const QString& uri, QString& errMsg ) const
{
QUrl url( uri );
QgsNetworkAccessManager* nam = QgsNetworkAccessManager::instance();
QNetworkReply* reply = nullptr;
while ( true )
{
QNetworkRequest req( url );
req.setRawHeader( "User-Agent" , "Wget/1.13.4" );
reply = nam->get( req );
QTimer timer;
QEventLoop loop;
QObject::connect( &timer, SIGNAL( timeout() ), &loop, SLOT( quit() ) );
QObject::connect( reply, SIGNAL( finished() ), &loop, SLOT( quit() ) );
timer.setSingleShot( true );
timer.start( 500 );
loop.exec();
if ( reply->isRunning() )
{
// Timeout
reply->close();
delete reply;
errMsg = tr( "Timeout" );
return false;
}
QUrl redirectUrl = reply->attribute( QNetworkRequest::RedirectionTargetAttribute ).toUrl();
if ( redirectUrl.isValid() && url != redirectUrl )
{
delete reply;
url = redirectUrl;
}
else
{
break;
}
}
errMsg = reply->error() == QNetworkReply::NoError ? QString() : reply->errorString();
delete reply;
return errMsg.isEmpty();
}
/// MAP ///////////////////////////////////////////////////////////////////////
void QgsGlobePluginDialog::addImagery( const QString& type, const QString& uri )
{
QTreeWidgetItem* item = new QTreeWidgetItem( QStringList() << type << uri );
item->setFlags( item->flags() & ~Qt::ItemIsDropEnabled );
mImageryTreeView->addTopLevelItem( item );
mImageryTreeView->resizeColumnToContents( 0 );
}
void QgsGlobePluginDialog::addTMSImagery()
{
addImagery( "TMS", qobject_cast<QAction*>( QObject::sender() )->data().toString() );
}
void QgsGlobePluginDialog::addCustomTMSImagery()
{
QString url = QInputDialog::getText( this, tr( "Add TMS Imagery" ), tr( "TMS URL:" ) );
if ( !url.isEmpty() )
{
QString validationError;
if ( !validateRemoteUri( url, validationError ) )
{
QMessageBox::warning( this, tr( "Invalid URL" ), validationError );
}
else
{
addImagery( "TMS", url );
}
}
}
void QgsGlobePluginDialog::addCustomWMSImagery()
{
QString url = QInputDialog::getText( this, tr( "Add WMS Imagery" ), tr( "URL:" ) );
if ( !url.isEmpty() )
{
QString validationError;
if ( !validateRemoteUri( url, validationError ) )
{
QMessageBox::warning( this, tr( "Invalid URL" ), validationError );
}
else
{
addImagery( "WMS", url );
}
}
}
void QgsGlobePluginDialog::addRasterImagery()
{
addImagery( "Raster", qobject_cast<QAction*>( QObject::sender() )->data().toString() );
}
void QgsGlobePluginDialog::addCustomRasterImagery()
{
QString filename = QFileDialog::getOpenFileName( this, tr( "Add Raster Imagery" ) );
if ( !filename.isEmpty() )
{
addImagery( "Raster", filename );
}
}
void QgsGlobePluginDialog::addElevation( const QString& type, const QString& uri )
{
QTreeWidgetItem* item = new QTreeWidgetItem( QStringList() << type << uri );
item->setFlags( item->flags() & ~Qt::ItemIsDropEnabled );
mElevationTreeView->addTopLevelItem( item );
mElevationTreeView->resizeColumnToContents( 0 );
}
void QgsGlobePluginDialog::addTMSElevation()
{
addElevation( "TMS", qobject_cast<QAction*>( QObject::sender() )->data().toString() );
}
void QgsGlobePluginDialog::addCustomTMSElevation()
{
QString url = QInputDialog::getText( this, tr( "Add TMS Elevation" ), tr( "TMS URL:" ) );
if ( !url.isEmpty() )
{
QString validationError;
if ( !validateRemoteUri( url, validationError ) )
{
QMessageBox::warning( this, tr( "Invalid URL" ), validationError );
}
else
{
addElevation( "TMS", url );
}
}
}
void QgsGlobePluginDialog::addCustomRasterElevation()
{
QString filename = QFileDialog::getOpenFileName( this, tr( "Add Raster Elevation" ) );
if ( !filename.isEmpty() )
{
addElevation( "Raster", filename );
}
}
void QgsGlobePluginDialog::on_mRemoveImageryButton_clicked()
{
delete mImageryTreeView->currentItem();
}
void QgsGlobePluginDialog::on_mRemoveElevationButton_clicked()
{
delete mElevationTreeView->currentItem();
}
QList<QgsGlobePluginDialog::LayerDataSource> QgsGlobePluginDialog::getImageryDataSources() const
{
int keysCount = QgsProject::instance()->subkeyList( "Globe-Plugin", "/imageryDatasources/" ).count();
QList<LayerDataSource> datasources;
for ( int i = 0; i < keysCount; ++i )
{
QString key = QString( "/imageryDatasources/L%1" ).arg( i );
LayerDataSource datasource;
datasource.type = QgsProject::instance()->readEntry( "Globe-Plugin", key + "/type" );
datasource.uri = QgsProject::instance()->readEntry( "Globe-Plugin", key + "/uri" );
datasources.append( datasource );
}
return datasources;
}
QList<QgsGlobePluginDialog::LayerDataSource> QgsGlobePluginDialog::getElevationDataSources() const
{
int keysCount = QgsProject::instance()->subkeyList( "Globe-Plugin", "/elevationDatasources/" ).count();
QList<LayerDataSource> datasources;
for ( int i = 0; i < keysCount; ++i )
{
QString key = QString( "/elevationDatasources/L%1" ).arg( i );
LayerDataSource datasource;
datasource.type = QgsProject::instance()->readEntry( "Globe-Plugin", key + "/type" );
datasource.uri = QgsProject::instance()->readEntry( "Globe-Plugin", key + "/uri" );
datasources.append( datasource );
}
return datasources;
}
double QgsGlobePluginDialog::getVerticalScale() const
{
return mSpinBoxVerticalScale->value();
}
bool QgsGlobePluginDialog::getSkyEnabled() const
{
return QgsProject::instance()->readBoolEntry( "Globe-Plugin", "/skyEnabled", true );
}
QDateTime QgsGlobePluginDialog::getSkyDateTime() const
{
return QDateTime::fromString( QgsProject::instance()->readEntry( "Globe-Plugin", "/skyDateTime", QDateTime::currentDateTime().toString() ) );
}
bool QgsGlobePluginDialog::getSkyAutoAmbience() const
{
return QgsProject::instance()->readBoolEntry( "Globe-Plugin", "/skyAutoAmbient", true );
}
double QgsGlobePluginDialog::getSkyMinAmbient() const
{
return QgsProject::instance()->readDoubleEntry( "Globe-Plugin", "/skyMinAmbient", 30. ) / 100.;
}
/// ADVANCED //////////////////////////////////////////////////////////////////
float QgsGlobePluginDialog::getScrollSensitivity() const
{
return sliderScrollSensitivity->value() / 10;
}
bool QgsGlobePluginDialog::getInvertScrollWheel() const
{
return checkBoxInvertScroll->checkState();
}
bool QgsGlobePluginDialog::getFrustumHighlighting() const
{
return checkBoxFrustumHighlighting->isChecked();
}
bool QgsGlobePluginDialog::getFeatureIdenification() const
{
return checkBoxFeatureIdentification->isChecked();
}
/// STEREO ////////////////////////////////////////////////////////////////////
void QgsGlobePluginDialog::on_pushButtonStereoResetDefaults_clicked()
{
//http://www.openscenegraph.org/projects/osg/wiki/Support/UserGuides/StereoSettings
comboBoxStereoMode->setCurrentIndex( comboBoxStereoMode->findText( "OFF" ) );
spinBoxStereoScreenDistance->setValue( 0.5 );
spinBoxStereoScreenHeight->setValue( 0.26 );
spinBoxStereoScreenWidth->setValue( 0.325 );
spinBoxStereoEyeSeparation->setValue( 0.06 );
spinBoxSplitStereoHorizontalSeparation->setValue( 42 );
spinBoxSplitStereoVerticalSeparation->setValue( 42 );
comboBoxSplitStereoHorizontalEyeMapping->setCurrentIndex( 0 );
comboBoxSplitStereoVerticalEyeMapping->setCurrentIndex( 0 );
}
void QgsGlobePluginDialog::on_comboBoxStereoMode_currentIndexChanged( int index )
{
//http://www.openscenegraph.org/projects/osg/wiki/Support/UserGuides/StereoSettings
//http://www.openscenegraph.org/documentation/OpenSceneGraphReferenceDocs/a00181.html
int stereoMode = comboBoxStereoMode->itemData( index ).toInt();
bool stereoEnabled = stereoMode != -1;
bool verticalSplit = stereoMode == osg::DisplaySettings::VERTICAL_SPLIT;
bool horizontalSplit = stereoMode == osg::DisplaySettings::HORIZONTAL_SPLIT;
spinBoxStereoScreenDistance->setEnabled( stereoEnabled );
spinBoxStereoScreenHeight->setEnabled( stereoEnabled );
spinBoxStereoScreenWidth->setEnabled( stereoEnabled );
spinBoxStereoEyeSeparation->setEnabled( stereoEnabled );
spinBoxSplitStereoHorizontalSeparation->setEnabled( stereoEnabled && horizontalSplit );
comboBoxSplitStereoHorizontalEyeMapping->setEnabled( stereoEnabled && horizontalSplit );
spinBoxSplitStereoVerticalSeparation->setEnabled( stereoEnabled && verticalSplit );
comboBoxSplitStereoVerticalEyeMapping->setEnabled( stereoEnabled && verticalSplit );
}

View File

@ -0,0 +1,83 @@
/***************************************************************************
qgsglobeplugindialog.h - settings dialog for the globe plugin
--------------------------------------
Date : 11-Nov-2010
Copyright : (C) 2010 by Marco Bernasocchi
Email : marco at bernawebdesign.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGLOBEPLUGINDIALOG_H
#define QGSGLOBEPLUGINDIALOG_H
#include <ui_qgsglobeplugindialog.h>
#include <QDialog>
class GlobePlugin;
class QgsVectorLayer;
class QgsGlobePluginDialog: public QDialog, private Ui::QgsGlobePluginDialogGuiBase
{
Q_OBJECT
public:
QgsGlobePluginDialog( QWidget * parent = 0, Qt::WFlags fl = 0 );
struct LayerDataSource
{
QString uri;
QString type;
bool operator==( const LayerDataSource& other ) { return uri == other.uri && type == other.type; }
bool operator!=( const LayerDataSource& other ) { return uri != other.uri || type != other.type; }
};
void readProjectSettings();
QString getBaseLayerUrl() const;
bool getSkyEnabled() const;
QDateTime getSkyDateTime() const;
bool getSkyAutoAmbience() const;
double getSkyMinAmbient() const;
float getScrollSensitivity() const;
bool getInvertScrollWheel() const;
QList<LayerDataSource> getImageryDataSources() const;
QList<LayerDataSource> getElevationDataSources() const;
double getVerticalScale() const;
bool getFrustumHighlighting() const;
bool getFeatureIdenification() const;
signals:
void settingsApplied();
private:
void restoreSavedSettings();
void writeProjectSettings();
bool validateRemoteUri( const QString &uri , QString &errMsg ) const;
private slots:
void apply();
void on_buttonBox_accepted();
void on_buttonBox_rejected();
void on_comboBoxStereoMode_currentIndexChanged( int index );
void on_pushButtonStereoResetDefaults_clicked();
void on_mRemoveImageryButton_clicked();
void on_mRemoveElevationButton_clicked();
void addImagery( const QString &type, const QString &uri );
void addTMSImagery();
void addCustomTMSImagery();
void addCustomWMSImagery();
void addRasterImagery();
void addCustomRasterImagery();
void addElevation( const QString &type, const QString &uri );
void addTMSElevation();
void addCustomTMSElevation();
void addCustomRasterElevation();
};
#endif // QGSGLOBEPLUGINDIALOG_H

View File

@ -0,0 +1,665 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsGlobePluginDialogGuiBase</class>
<widget class="QDialog" name="QgsGlobePluginDialogGuiBase">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>748</width>
<height>519</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Globe Settings</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>../../.designer/backup</normaloff>../../.designer/backup</iconset>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tabMap">
<attribute name="title">
<string>Map</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="2" column="0">
<widget class="QGroupBox" name="groupBoxSky">
<property name="title">
<string>Sk&amp;y</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="labelDateTime">
<property name="text">
<string>Date / Time (UTC):</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDateTimeEdit" name="dateTimeEditSky">
<property name="displayFormat">
<string>dd.MM.yyyy HH:mm</string>
</property>
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkBoxSkyAutoAmbient">
<property name="text">
<string>Ambient lighting</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="horizontalSliderMinAmbient">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedControls">
<bool>false</bool>
</property>
<property name="tickPosition">
<enum>QSlider::NoTicks</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="mImageryGroupBox">
<property name="title">
<string>Imagery</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTreeWidget" name="mImageryTreeView">
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="indentation">
<number>0</number>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerDefaultSectionSize">
<number>50</number>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">2</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="mAddImageryButton">
<property name="text">
<string>Add</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mRemoveImageryButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<spacer name="verticalSpacerMapTab">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="mElevationGroupBox">
<property name="title">
<string>Elevation</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="0">
<widget class="QLabel" name="labelVerticalScale">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Vertical scale:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="mSpinBoxVerticalScale">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTreeWidget" name="mElevationTreeView">
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="indentation">
<number>0</number>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerDefaultSectionSize">
<number>50</number>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">2</string>
</property>
</column>
</widget>
</item>
<item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="mAddElevationButton">
<property name="text">
<string>Add</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mRemoveElevationButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabVideo">
<attribute name="title">
<string>Video</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_8">
<item row="1" column="0">
<widget class="QGroupBox" name="groupBoxAntiAliasing">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Anti Aliasing</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="labelAASamples">
<property name="text">
<string>Samples</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditAASamples">
<property name="placeholderText">
<string>[Leave empty for maximum]</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="labelVideoInfo">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Change requires a restart of the globe plugin&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacerVideoTab">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Stereo</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QLabel" name="labelStereoMode">
<property name="text">
<string>Stereo Mode</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxStereoMode"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelEyeSeparation">
<property name="text">
<string>Eye separation (m)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="spinBoxStereoEyeSeparation">
<property name="readOnly">
<bool>false</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="accelerated">
<bool>true</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelScreenDistance">
<property name="text">
<string>Screen distance (m)</string>
</property>
<property name="buddy">
<cstring>spinBoxStereoScreenDistance</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="spinBoxStereoScreenDistance">
<property name="accelerated">
<bool>true</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelScreenWidth">
<property name="text">
<string>Screen width (m)</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="spinBoxStereoScreenWidth">
<property name="accelerated">
<bool>true</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelScreenHeight">
<property name="text">
<string>Screen height (m)</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="spinBoxStereoScreenHeight">
<property name="accelerated">
<bool>true</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelSplitStereoHorizontalSeparation">
<property name="text">
<string>Split stereo horizontal separation (px)</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="spinBoxSplitStereoHorizontalSeparation">
<property name="enabled">
<bool>true</bool>
</property>
<property name="accelerated">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="labelSplitStereoHorizontalEyeMapping">
<property name="text">
<string>Split stereo horizontal eye mapping</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="comboBoxSplitStereoHorizontalEyeMapping">
<item>
<property name="text">
<string notr="true">LEFT_EYE_LEFT_VIEWPORT</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">LEFT_EYE_RIGHT_VIEWPORT</string>
</property>
</item>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="labelSplitStereoVerticalSeparation">
<property name="text">
<string>Split stereo vertical separation (px)</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSpinBox" name="spinBoxSplitStereoVerticalSeparation">
<property name="accelerated">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="labelBoxSplitStereoVerticalEyeMapping">
<property name="text">
<string>Split stereo vertical eye mapping</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="comboBoxSplitStereoVerticalEyeMapping">
<property name="enabled">
<bool>true</bool>
</property>
<item>
<property name="text">
<string notr="true">LEFT_EYE_TOP_VIEWPORT</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">LEFT_EYE_BOTTOM_VIEWPORT</string>
</property>
</item>
</widget>
</item>
<item row="9" column="1">
<widget class="QPushButton" name="pushButtonStereoResetDefaults">
<property name="text">
<string>Reset to defaults</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabAdvanced">
<attribute name="title">
<string>Advanced</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBoxScrolling">
<property name="title">
<string>Scrolling</string>
</property>
<layout class="QGridLayout" name="gridLayout_9">
<item row="2" column="0">
<widget class="QLabel" name="labelScollSensitivity">
<property name="text">
<string>Sensitivity:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="sliderScrollSensitivity">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>20</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxInvertScroll">
<property name="text">
<string>Invert scroll wheel</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxFeatureIdentification">
<property name="text">
<string>Enable feature identification</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxFrustumHighlighting">
<property name="text">
<string>Enable frustum highlighting</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacerAdvancedTab">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,301 @@
/***************************************************************************
qgsglobetilesource.cpp
---------------------
begin : August 2010
copyright : (C) 2010 by Pirmin Kalberer
(C) 2015 Sandro Mani
email : pka at sourcepole dot ch
smani at sourcepole dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <osgEarth/Registry>
#include <osgEarth/ImageUtils>
#include "qgscrscache.h"
#include "qgsglobetilesource.h"
#include "qgscoordinatetransform.h"
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsmaprenderercustompainterjob.h"
#include "qgsmaprendererparalleljob.h"
QgsGlobeTileStatistics* QgsGlobeTileStatistics::s_instance = 0;
QgsGlobeTileStatistics::QgsGlobeTileStatistics() : mTileCount( 0 ), mQueueTileCount( 0 )
{
s_instance = this;
}
void QgsGlobeTileStatistics::updateTileCount( int change )
{
mMutex.lock();
mTileCount += change;
emit changed( mQueueTileCount, mTileCount );
mMutex.unlock();
}
void QgsGlobeTileStatistics::updateQueueTileCount( int num )
{
mMutex.lock();
mQueueTileCount = num;
emit changed( mQueueTileCount, mTileCount );
mMutex.unlock();
}
///////////////////////////////////////////////////////////////////////////////
QgsGlobeTileImage::QgsGlobeTileImage( QgsGlobeTileSource* tileSource, const QgsRectangle& tileExtent, int tileSize , int tileLod )
: osg::Image()
, mTileSource( tileSource )
, mTileExtent( tileExtent )
, mTileSize( tileSize )
, mImageUpdatePending( false )
, mLod( tileLod )
{
#ifdef GLOBE_SHOW_TILE_STATS
QgsGlobeTileStatistics::instance()->updateTileCount( + 1 );
#endif
mTileData = new unsigned char[mTileSize * mTileSize * 4];
std::memset( mTileData, 0, mTileSize * mTileSize * 4 );
#if 0
setImage( mTileSize, mTileSize, 1, 4, // width, height, depth, internal_format
GL_BGRA, GL_UNSIGNED_BYTE,
mTileData, osg::Image::NO_DELETE );
mLastUpdateTime = osgEarth::DateTime().asTimeStamp();
mTileSource->mTileUpdateManager.addTile( const_cast<QgsGlobeTileImage*>( this ) );
mDpi = 72;
mImageUpdatePending = true;
#else
QImage qImage( mTileData, mTileSize, mTileSize, QImage::Format_ARGB32_Premultiplied );
QPainter painter( &qImage );
QgsMapRendererCustomPainterJob job( createSettings( qImage.logicalDpiX(), mTileSource->mLayerSet ), &painter );
job.renderSynchronously();
setImage( mTileSize, mTileSize, 1, 4, // width, height, depth, internal_format
GL_BGRA, GL_UNSIGNED_BYTE,
mTileData, osg::Image::NO_DELETE );
flipVertical();
mDpi = qImage.logicalDpiX();
mLastUpdateTime = osgEarth::DateTime().asTimeStamp();
#endif
}
QgsGlobeTileImage::~QgsGlobeTileImage()
{
mTileSource->mTileUpdateManager.removeTile( this );
delete[] mTileData;
#ifdef GLOBE_SHOW_TILE_STATS
QgsGlobeTileStatistics::instance()->updateTileCount( -1 );
#endif
}
bool QgsGlobeTileImage::requiresUpdateCall() const
{
if ( mLastUpdateTime < mTileSource->mLastModifiedTime )
{
mLastUpdateTime = mTileSource->mLastModifiedTime;
if ( !mTileExtent.intersects( mTileSource->mLastUpdateExtent ) )
{
return false;
}
mTileSource->mTileUpdateManager.addTile( const_cast<QgsGlobeTileImage*>( this ) );
mImageUpdatePending = true;
return true;
}
return mImageUpdatePending;
}
QgsMapSettings QgsGlobeTileImage::createSettings( int dpi , const QStringList &layerSet ) const
{
QgsMapSettings settings;
settings.setBackgroundColor( QColor( Qt::transparent ) );
settings.setDestinationCrs( QgsCRSCache::instance()->crsByAuthId( GEO_EPSG_CRS_AUTHID ) );
settings.setCrsTransformEnabled( true );
settings.setExtent( mTileExtent );
settings.setLayers( layerSet );
settings.setFlag( QgsMapSettings::DrawEditingInfo, false );
settings.setFlag( QgsMapSettings::DrawLabeling, false );
settings.setFlag( QgsMapSettings::DrawSelection, false );
settings.setMapUnits( QGis::Degrees );
settings.setOutputSize( QSize( mTileSize, mTileSize ) );
settings.setOutputImageFormat( QImage::Format_ARGB32_Premultiplied );
settings.setOutputDpi( dpi );
settings.setCustomRenderFlags( "globe" );
return settings;
}
void QgsGlobeTileImage::update( osg::NodeVisitor * )
{
if ( !mUpdatedImage.isNull() )
{
QgsDebugMsg( QString( "Updating earth tile image: %1" ).arg( mTileExtent.toString( 5 ) ) );
std::memcpy( mTileData, mUpdatedImage.bits(), mTileSize * mTileSize * 4 );
setImage( mTileSize, mTileSize, 1, 4, // width, height, depth, internal_format
GL_BGRA, GL_UNSIGNED_BYTE,
mTileData, osg::Image::NO_DELETE );
flipVertical();
mUpdatedImage = QImage();
mImageUpdatePending = false;
}
}
///////////////////////////////////////////////////////////////////////////////
QgsGlobeTileUpdateManager::QgsGlobeTileUpdateManager( QObject* parent )
: QObject( parent ), mCurrentTile( 0 ), mRenderer( 0 )
{
connect( this, SIGNAL( startRendering() ), this, SLOT( start() ) );
connect( this, SIGNAL( cancelRendering() ), this, SLOT( cancel() ) );
}
QgsGlobeTileUpdateManager::~QgsGlobeTileUpdateManager()
{
#ifdef GLOBE_SHOW_TILE_STATS
QgsGlobeTileStatistics::instance()->updateQueueTileCount( 0 );
#endif
mTileQueue.clear();
mCurrentTile = 0;
if ( mRenderer )
{
mRenderer->cancel();
}
}
void QgsGlobeTileUpdateManager::addTile( QgsGlobeTileImage *tile )
{
if ( !mTileQueue.contains( tile ) )
{
mTileQueue.append( tile );
#ifdef GLOBE_SHOW_TILE_STATS
QgsGlobeTileStatistics::instance()->updateQueueTileCount( mTileQueue.size() );
#endif
qSort( mTileQueue.begin(), mTileQueue.end(), QgsGlobeTileImage::lodSort );
}
emit startRendering();
}
void QgsGlobeTileUpdateManager::removeTile( QgsGlobeTileImage *tile )
{
if ( mCurrentTile == tile )
{
mCurrentTile = 0;
if ( mRenderer )
emit cancelRendering();
}
else if ( mTileQueue.contains( tile ) )
{
mTileQueue.removeAll( tile );
#ifdef GLOBE_SHOW_TILE_STATS
QgsGlobeTileStatistics::instance()->updateQueueTileCount( mTileQueue.size() );
#endif
}
}
void QgsGlobeTileUpdateManager::start()
{
if ( mRenderer == 0 && !mTileQueue.isEmpty() )
{
mCurrentTile = mTileQueue.takeFirst();
#ifdef GLOBE_SHOW_TILE_STATS
QgsGlobeTileStatistics::instance()->updateQueueTileCount( mTileQueue.size() );
#endif
mRenderer = new QgsMapRendererParallelJob( mCurrentTile->createSettings( mCurrentTile->dpi(), mLayerSet ) );
connect( mRenderer, SIGNAL( finished() ), this, SLOT( renderingFinished() ) );
mRenderer->start();
}
}
void QgsGlobeTileUpdateManager::cancel()
{
if ( mRenderer )
mRenderer->cancel();
}
void QgsGlobeTileUpdateManager::renderingFinished()
{
if ( mCurrentTile )
{
QImage image = mRenderer->renderedImage();
mCurrentTile->setUpdatedImage( image );
mCurrentTile = 0;
}
mRenderer->deleteLater();
mRenderer = 0;
start();
}
///////////////////////////////////////////////////////////////////////////////
QgsGlobeTileSource::QgsGlobeTileSource( QgsMapCanvas* canvas, const osgEarth::TileSourceOptions& options )
: TileSource( options )
, mCanvas( canvas )
, mLastModifiedTime( 0 )
{
}
osgEarth::TileSource::Status QgsGlobeTileSource::initialize( const osgDB::Options* /*dbOptions*/ )
{
setProfile( osgEarth::Registry::instance()->getGlobalGeodeticProfile() );
mLastModifiedTime = osgEarth::DateTime().asTimeStamp();
return STATUS_OK;
}
osg::Image* QgsGlobeTileSource::createImage( const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress )
{
Q_UNUSED( progress );
int tileSize = getPixelsPerTile();
if ( tileSize <= 0 )
{
return osgEarth::ImageUtils::createEmptyImage();
}
double xmin, ymin, xmax, ymax;
key.getExtent().getBounds( xmin, ymin, xmax, ymax );
QgsRectangle tileExtent( xmin, ymin, xmax, ymax );
QgsDebugMsg( QString( "Create earth tile image: %1" ).arg( tileExtent.toString( 5 ) ) );
return new QgsGlobeTileImage( this, tileExtent, getPixelsPerTile(), key.getLOD() );
}
bool QgsGlobeTileSource::hasDataInExtent( const osgEarth::GeoExtent &extent ) const
{
osgEarth::Bounds bounds = extent.bounds();
QgsRectangle requestExtent( bounds.xMin(), bounds.yMin(), bounds.xMax(), bounds.yMax() );
return requestExtent.intersects( mViewExtent );
}
bool QgsGlobeTileSource::hasData( const osgEarth::TileKey& key ) const
{
const osgEarth::GeoExtent& tileExtent = key.getExtent();
QgsRectangle rect( tileExtent.xMin(), tileExtent.yMin(), tileExtent.xMax(), tileExtent.yMax() );
return rect.intersects( mViewExtent );
}
void QgsGlobeTileSource::refresh( const QgsRectangle& updateExtent )
{
osgEarth::TimeStamp old = mLastModifiedTime;
mLastModifiedTime = osgEarth::DateTime().asTimeStamp();
mTileUpdateManager.updateLayerSet( mLayerSet );
mLastUpdateExtent = updateExtent;
QgsDebugMsg( QString( "Updated QGIS map layer modified time from %1 to %2" ).arg( old ).arg( mLastModifiedTime ) );
mViewExtent = QgsCoordinateTransformCache::instance()->transform( mCanvas->mapSettings().destinationCrs().authid(), GEO_EPSG_CRS_AUTHID )->transform( mCanvas->fullExtent() );
}
void QgsGlobeTileSource::setLayerSet( const QStringList &layerSet )
{
mLayerSet = layerSet;
}
const QStringList& QgsGlobeTileSource::layerSet() const
{
return mLayerSet;
}

View File

@ -0,0 +1,138 @@
/***************************************************************************
qgsglobetilesource.h
---------------------
begin : August 2010
copyright : (C) 2010 by Pirmin Kalberer
(C) 2015 Sandro Mani
email : pka at sourcepole dot ch
smani at sourcepole dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGLOBETILESOURCE_H
#define QGSGLOBETILESOURCE_H
#include <osgEarth/TileSource>
#include <osg/ImageStream>
#include <QImage>
#include <QStringList>
#include <QLabel>
#include <QMutex>
#include "qgsrectangle.h"
//#define GLOBE_SHOW_TILE_STATS
class QgsCoordinateTransform;
class QgsMapCanvas;
class QgsMapRenderer;
class QgsMapSettings;
class QgsGlobeTileSource;
class QgsMapRendererParallelJob;
class QgsGlobeTileStatistics : public QObject
{
Q_OBJECT
public:
QgsGlobeTileStatistics();
~QgsGlobeTileStatistics() { s_instance = 0; }
static QgsGlobeTileStatistics* instance() { return s_instance; }
void updateTileCount( int change );
void updateQueueTileCount( int change );
signals:
void changed( int queued, int tot );
private:
static QgsGlobeTileStatistics* s_instance;
QMutex mMutex;
int mTileCount;
int mQueueTileCount;
};
int getTileCount();
class QgsGlobeTileImage : public osg::Image
{
public:
QgsGlobeTileImage( QgsGlobeTileSource* tileSource, const QgsRectangle& tileExtent, int tileSize, int tileLod );
~QgsGlobeTileImage();
bool requiresUpdateCall() const;
QgsMapSettings createSettings( int dpi, const QStringList &layerSet ) const;
void setUpdatedImage( const QImage& image ) { mUpdatedImage = image; }
int dpi() const { return mDpi; }
void update( osg::NodeVisitor * );
static bool lodSort( const QgsGlobeTileImage* lhs, const QgsGlobeTileImage* rhs ) { return lhs->mLod > rhs->mLod; }
private:
QgsGlobeTileSource* mTileSource;
QgsRectangle mTileExtent;
mutable osgEarth::TimeStamp mLastUpdateTime;
int mTileSize;
unsigned char* mTileData;
mutable bool mImageUpdatePending;
int mLod;
int mDpi;
QImage mUpdatedImage;
};
class QgsGlobeTileUpdateManager : public QObject
{
Q_OBJECT
public:
QgsGlobeTileUpdateManager( QObject* parent = 0 );
~QgsGlobeTileUpdateManager();
void updateLayerSet( const QStringList& layerSet ) { mLayerSet = layerSet; }
void addTile( QgsGlobeTileImage* tile );
void removeTile( QgsGlobeTileImage* tile );
signals:
void startRendering();
void cancelRendering();
private:
QStringList mLayerSet;
QList<QgsGlobeTileImage*> mTileQueue;
QgsGlobeTileImage* mCurrentTile;
QgsMapRendererParallelJob* mRenderer;
private slots:
void start();
void cancel();
void renderingFinished();
};
class QgsGlobeTileSource : public osgEarth::TileSource
{
public:
QgsGlobeTileSource( QgsMapCanvas* canvas, const osgEarth::TileSourceOptions& options = osgEarth::TileSourceOptions() );
Status initialize( const osgDB::Options *dbOptions ) override;
osg::Image* createImage( const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress );
osg::HeightField* createHeightField( const osgEarth::TileKey &/*key*/, osgEarth::ProgressCallback* /*progress*/ ) { return 0; }
bool hasDataInExtent( const osgEarth::GeoExtent &extent ) const override;
bool hasData( const osgEarth::TileKey& key ) const override;
bool isDynamic() const { return true; }
osgEarth::TimeStamp getLastModifiedTime() const { return mLastModifiedTime; }
void refresh( const QgsRectangle &updateExtent );
void setLayerSet( const QStringList& layerSet );
const QStringList &layerSet() const;
private:
friend class QgsGlobeTileImage;
QgsMapCanvas* mCanvas;
osgEarth::TimeStamp mLastModifiedTime;
QgsRectangle mViewExtent;
QgsRectangle mLastUpdateExtent;
QStringList mLayerSet;
QgsGlobeTileUpdateManager mTileUpdateManager;
};
#endif // QGSGLOBETILESOURCE_H

View File

@ -0,0 +1,288 @@
/***************************************************************************
qgsglobevectorlayerpropertiespage.cpp
--------------------------------------
Date : 9.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <qgsproject.h>
#include <qgsvectorlayer.h>
#include "qgsglobevectorlayerproperties.h"
#include <osgEarth/Version>
Q_DECLARE_METATYPE( QgsGlobeVectorLayerConfig* )
QgsGlobeVectorLayerConfig* QgsGlobeVectorLayerConfig::getConfig( QgsVectorLayer* layer )
{
QgsGlobeVectorLayerConfig* layerConfig = layer->property( "globe-config" ).value<QgsGlobeVectorLayerConfig*>();
if ( !layerConfig )
{
layerConfig = new QgsGlobeVectorLayerConfig( layer );
layer->setProperty( "globe-config", QVariant::fromValue<QgsGlobeVectorLayerConfig*>( layerConfig ) );
}
return layerConfig;
}
///////////////////////////////////////////////////////////////////////////////
QgsGlobeVectorLayerPropertiesPage::QgsGlobeVectorLayerPropertiesPage( QgsVectorLayer* layer, QWidget *parent )
: QgsVectorLayerPropertiesPage( parent )
, mLayer( layer )
{
setupUi( this );
// Populate combo boxes
comboBoxRenderingMode->addItem( tr( "Rasterized" ), QgsGlobeVectorLayerConfig::RenderingModeRasterized );
comboBoxRenderingMode->addItem( tr( "Model (Simple)" ), QgsGlobeVectorLayerConfig::RenderingModeModelSimple );
comboBoxRenderingMode->addItem( tr( "Model (Advanced)" ), QgsGlobeVectorLayerConfig::RenderingModeModelAdvanced );
comboBoxRenderingMode->setItemData( 0, tr( "Rasterize the layer to a texture, and drape it on the terrain" ), Qt::ToolTipRole );
comboBoxRenderingMode->setItemData( 1, tr( "Render the layer features as models" ), Qt::ToolTipRole );
comboBoxRenderingMode->setCurrentIndex( -1 );
comboBoxAltitudeClamping->addItem( tr( "None" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::CLAMP_NONE ) );
comboBoxAltitudeClamping->addItem( tr( "Terrain" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::CLAMP_TO_TERRAIN ) );
comboBoxAltitudeClamping->addItem( tr( "Relative" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN ) );
comboBoxAltitudeClamping->addItem( tr( "Absolute" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::CLAMP_ABSOLUTE ) );
comboBoxAltitudeClamping->setItemData( 0, tr( "Do not clamp Z values to the terrain (but still apply the offset, if applicable)" ), Qt::ToolTipRole );
comboBoxAltitudeClamping->setItemData( 1, tr( "Sample the terrain under the point, and set the feature's Z to the terrain height, ignoring the feature's original Z value" ), Qt::ToolTipRole );
comboBoxAltitudeClamping->setItemData( 2, tr( "Sample the terrain under the point, and add the terrain height to the feature's original Z value" ), Qt::ToolTipRole );
comboBoxAltitudeClamping->setItemData( 3, tr( "The feature's Z value describes its height above \"height zero\", which is typically the ellipsoid or MSL" ), Qt::ToolTipRole );
comboBoxAltitudeClamping->setCurrentIndex( -1 );
comboBoxAltitudeTechnique->addItem( tr( "Map" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_MAP ) );
comboBoxAltitudeTechnique->addItem( tr( "Drape" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_DRAPE ) );
comboBoxAltitudeTechnique->addItem( tr( "GPU" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_GPU ) );
comboBoxAltitudeTechnique->addItem( tr( "Scene" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_SCENE ) );
comboBoxAltitudeTechnique->setItemData( 0, tr( "Clamp geometry to the map model's elevation data" ), Qt::ToolTipRole );
comboBoxAltitudeTechnique->setItemData( 1, tr( "Clamp geometry to the terrain's scene graph" ), Qt::ToolTipRole );
comboBoxAltitudeTechnique->setItemData( 2, tr( "Clamp geometry to the terrain as they are rendered by the GPU" ), Qt::ToolTipRole );
comboBoxAltitudeTechnique->setItemData( 3, tr( "Clamp geometry at draw time using projective texturing" ), Qt::ToolTipRole );
comboBoxAltitudeTechnique->setCurrentIndex( -1 );
comboBoxAltitudeBinding->addItem( tr( "Vertex" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::BINDING_VERTEX ) );
comboBoxAltitudeBinding->addItem( tr( "Centroid" ), static_cast<int>( osgEarth::Symbology::AltitudeSymbol::BINDING_CENTROID ) );
comboBoxAltitudeBinding->setItemData( 0, tr( "Clamp every vertex independently" ), Qt::ToolTipRole );
comboBoxAltitudeBinding->setItemData( 1, tr( "Clamp to the centroid of the entire geometry" ), Qt::ToolTipRole );
comboBoxAltitudeBinding->setCurrentIndex( -1 );
// Connect signals (setCurrentIndex(-1) above ensures the signal is called when the current values are set below)
connect( comboBoxRenderingMode, SIGNAL( currentIndexChanged( int ) ), this, SLOT( showRenderingModeWidget( int ) ) );
connect( comboBoxAltitudeClamping, SIGNAL( currentIndexChanged( int ) ), this, SLOT( onAltitudeClampingChanged( int ) ) );
connect( comboBoxAltitudeTechnique, SIGNAL( currentIndexChanged( int ) ), this, SLOT( onAltituteTechniqueChanged( int ) ) );
// Set values
QgsGlobeVectorLayerConfig* layerConfig = QgsGlobeVectorLayerConfig::getConfig( mLayer );
comboBoxRenderingMode->setCurrentIndex( comboBoxRenderingMode->findData( static_cast<int>( layerConfig->renderingMode ) ) );
comboBoxAltitudeClamping->setCurrentIndex( comboBoxAltitudeClamping->findData( static_cast<int>( layerConfig->altitudeClamping ) ) );
comboBoxAltitudeTechnique->setCurrentIndex( comboBoxAltitudeTechnique->findData( static_cast<int>( layerConfig->altitudeTechnique ) ) );
comboBoxAltitudeBinding->setCurrentIndex( comboBoxAltitudeBinding->findData( static_cast<int>( layerConfig->altitudeBinding ) ) );
spinBoxAltitudeOffset->setValue( layerConfig->verticalOffset );
spinBoxAltitudeScale->setValue( layerConfig->verticalScale );
spinBoxAltitudeResolution->setValue( layerConfig->clampingResolution );
groupBoxExtrusion->setChecked( layerConfig->extrusionEnabled );
labelExtrusionHeight->setText( layerConfig->extrusionHeight );
checkBoxExtrusionFlatten->setChecked( layerConfig->extrusionFlatten );
spinBoxExtrusionWallGradient->setValue( layerConfig->extrusionWallGradient );
#if OSGEARTH_VERSION_LESS_THAN(2, 7, 0)
groupBoxLabelingEnabled->setChecked( layerConfig->labelingEnabled );
checkBoxLabelingDeclutter->setChecked( layerConfig->labelingDeclutter );
#else
#pragma message("TODO: labeling broken with osgEarth 2.7")
groupBoxLabelingEnabled->setChecked( false );
checkBoxLabelingDeclutter->setChecked( false );
groupBoxLabelingEnabled->setVisible( false );
checkBoxLabelingDeclutter->setVisible( false );
#endif
checkBoxLighting->setChecked( layerConfig->lightingEnabled );
}
void QgsGlobeVectorLayerPropertiesPage::apply()
{
QgsGlobeVectorLayerConfig* layerConfig = QgsGlobeVectorLayerConfig::getConfig( mLayer );
layerConfig->renderingMode = static_cast<QgsGlobeVectorLayerConfig::RenderingMode>( comboBoxRenderingMode->itemData( comboBoxRenderingMode->currentIndex() ).toInt() );
layerConfig->altitudeClamping = static_cast<osgEarth::Symbology::AltitudeSymbol::Clamping>( comboBoxAltitudeClamping->itemData( comboBoxAltitudeClamping->currentIndex() ).toInt() );
layerConfig->altitudeTechnique = static_cast<osgEarth::Symbology::AltitudeSymbol::Technique>( comboBoxAltitudeTechnique->itemData( comboBoxAltitudeTechnique->currentIndex() ).toInt() );
layerConfig->altitudeBinding = static_cast<osgEarth::Symbology::AltitudeSymbol::Binding>( comboBoxAltitudeBinding->itemData( comboBoxAltitudeBinding->currentIndex() ).toInt() );
layerConfig->verticalOffset = spinBoxAltitudeOffset->value();
layerConfig->verticalScale = spinBoxAltitudeScale->value();
layerConfig->clampingResolution = spinBoxAltitudeResolution->value();
layerConfig->extrusionEnabled = groupBoxExtrusion->isChecked();
layerConfig->extrusionHeight = labelExtrusionHeight->text();
layerConfig->extrusionFlatten = checkBoxExtrusionFlatten->isChecked();
layerConfig->extrusionWallGradient = spinBoxExtrusionWallGradient->value();
layerConfig->labelingEnabled = groupBoxLabelingEnabled->isChecked();
layerConfig->labelingDeclutter = checkBoxLabelingDeclutter->isChecked();
layerConfig->lightingEnabled = checkBoxLighting->isChecked();
emit layerSettingsChanged( mLayer );
}
void QgsGlobeVectorLayerPropertiesPage::onAltitudeClampingChanged( int index )
{
osgEarth::Symbology::AltitudeSymbol::Clamping clamping = static_cast<osgEarth::Symbology::AltitudeSymbol::Clamping>( comboBoxAltitudeClamping->itemData( index ).toInt() );
bool terrainClamping = clamping == osgEarth::Symbology::AltitudeSymbol::CLAMP_TO_TERRAIN;
labelAltitudeTechnique->setVisible( terrainClamping );
comboBoxAltitudeTechnique->setVisible( terrainClamping );
onAltituteTechniqueChanged( comboBoxAltitudeTechnique->currentIndex() );
}
void QgsGlobeVectorLayerPropertiesPage::onAltituteTechniqueChanged( int index )
{
osgEarth::Symbology::AltitudeSymbol::Clamping clamping = static_cast<osgEarth::Symbology::AltitudeSymbol::Clamping>( comboBoxAltitudeClamping->itemData( comboBoxAltitudeClamping->currentIndex() ).toInt() );
osgEarth::Symbology::AltitudeSymbol::Technique technique = static_cast<osgEarth::Symbology::AltitudeSymbol::Technique>( comboBoxAltitudeTechnique->itemData( index ).toInt() );
bool mapTechnique = technique == osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_MAP && clamping == osgEarth::Symbology::AltitudeSymbol::CLAMP_TO_TERRAIN;
labelAltitudeBinding->setVisible( mapTechnique );
comboBoxAltitudeBinding->setVisible( mapTechnique );
labelAltitudeResolution->setVisible( mapTechnique );
spinBoxAltitudeResolution->setVisible( mapTechnique );
}
void QgsGlobeVectorLayerPropertiesPage::showRenderingModeWidget( int index )
{
stackedWidgetRenderingMode->setCurrentIndex( index != 0 );
bool advanced = index == 2;
groupBoxAltitude->setVisible( advanced );
checkBoxLighting->setVisible( advanced );
checkBoxExtrusionFlatten->setVisible( advanced );
if ( !advanced )
{
comboBoxAltitudeClamping->setCurrentIndex( comboBoxAltitudeClamping->findData( static_cast<int>( osgEarth::Symbology::AltitudeSymbol::CLAMP_TO_TERRAIN ) ) );
comboBoxAltitudeTechnique->setCurrentIndex( comboBoxAltitudeTechnique->findData( static_cast<int>( osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_GPU ) ) );
spinBoxAltitudeResolution->setValue( 0 );
spinBoxAltitudeOffset->setValue( 0 );
spinBoxAltitudeScale->setValue( 0 );
checkBoxExtrusionFlatten->setChecked( false );
}
}
///////////////////////////////////////////////////////////////////////////////
QgsGlobeLayerPropertiesFactory::QgsGlobeLayerPropertiesFactory( QObject *parent )
: QObject( parent )
{
connect( QgsProject::instance(), SIGNAL( readMapLayer( QgsMapLayer*, QDomElement ) ), this, SLOT( readGlobeVectorLayerConfig( QgsMapLayer*, QDomElement ) ) );
connect( QgsProject::instance(), SIGNAL( writeMapLayer( QgsMapLayer*, QDomElement&, QDomDocument& ) ), this, SLOT( writeGlobeVectorLayerConfig( QgsMapLayer*, QDomElement&, QDomDocument& ) ) );
}
QgsVectorLayerPropertiesPage* QgsGlobeLayerPropertiesFactory::createVectorLayerPropertiesPage( QgsVectorLayer* layer, QWidget* parent )
{
QgsGlobeVectorLayerPropertiesPage* propsPage = new QgsGlobeVectorLayerPropertiesPage( layer, parent );
connect( propsPage, SIGNAL( layerSettingsChanged( QgsMapLayer* ) ), this, SIGNAL( layerSettingsChanged( QgsMapLayer* ) ) );
return propsPage;
}
QListWidgetItem* QgsGlobeLayerPropertiesFactory::createVectorLayerPropertiesItem( QgsVectorLayer* layer, QListWidget* view )
{
Q_UNUSED( layer );
return new QListWidgetItem( QIcon( ":/globe/icon.svg" ), tr( "Globe" ), view );
}
void QgsGlobeLayerPropertiesFactory::readGlobeVectorLayerConfig( QgsMapLayer* mapLayer, const QDomElement& elem )
{
if ( dynamic_cast<QgsVectorLayer*>( mapLayer ) )
{
QgsVectorLayer* vLayer = static_cast<QgsVectorLayer*>( mapLayer );
QgsGlobeVectorLayerConfig* config = QgsGlobeVectorLayerConfig::getConfig( vLayer );
QDomElement globeElem = elem.firstChildElement( "globe" );
if ( !globeElem.isNull() )
{
QDomElement renderingModeElem = globeElem.firstChildElement( "renderingMode" );
config->renderingMode = static_cast<QgsGlobeVectorLayerConfig::RenderingMode>( renderingModeElem.attribute( "mode" ).toInt() );
QDomElement modelRenderingElem = globeElem.firstChildElement( "modelRendering" );
if ( !modelRenderingElem.isNull() )
{
QDomElement altitudeElem = modelRenderingElem.firstChildElement( "altitude" );
config->altitudeClamping = static_cast<osgEarth::Symbology::AltitudeSymbol::Clamping>( altitudeElem.attribute( "clamping" ).toInt() );
config->altitudeTechnique = static_cast<osgEarth::Symbology::AltitudeSymbol::Technique>( altitudeElem.attribute( "technique" ).toInt() );
config->altitudeBinding = static_cast<osgEarth::Symbology::AltitudeSymbol::Binding>( altitudeElem.attribute( "binding" ).toInt() );
config->verticalOffset = altitudeElem.attribute( "verticalOffset" ).toFloat();
config->verticalScale = altitudeElem.attribute( "verticalScale" ).toFloat();
config->clampingResolution = altitudeElem.attribute( "clampingResolution" ).toFloat();
QDomElement extrusionElem = modelRenderingElem.firstChildElement( "extrusion" );
config->extrusionEnabled = extrusionElem.attribute( "enabled" ).toInt() == 1;
config->extrusionHeight = extrusionElem.attribute( "height", QString( "10" ) ).trimmed();
if ( config->extrusionHeight.isEmpty() )
config->extrusionHeight = "10";
config->extrusionFlatten = extrusionElem.attribute( "flatten" ).toInt() == 1;
config->extrusionWallGradient = extrusionElem.attribute( "wall-gradient" ).toDouble();
QDomElement labelingElem = modelRenderingElem.firstChildElement( "labeling" );
config->labelingEnabled = labelingElem.attribute( "enabled", "0" ).toInt() == 1;
config->labelingField = labelingElem.attribute( "field" );
config->labelingDeclutter = labelingElem.attribute( "declutter", "1" ).toInt() == 1;
config->lightingEnabled = modelRenderingElem.attribute( "lighting", "1" ).toInt() == 1;
}
}
}
}
void QgsGlobeLayerPropertiesFactory::writeGlobeVectorLayerConfig( QgsMapLayer* mapLayer, QDomElement& elem, QDomDocument& doc )
{
if ( dynamic_cast<QgsVectorLayer*>( mapLayer ) )
{
QgsVectorLayer* vLayer = static_cast<QgsVectorLayer*>( mapLayer );
QgsGlobeVectorLayerConfig* config = QgsGlobeVectorLayerConfig::getConfig( vLayer );
QDomElement globeElem = doc.createElement( "globe" );
QDomElement renderingModeElem = doc.createElement( "renderingMode" );
renderingModeElem.setAttribute( "mode", config->renderingMode );
globeElem.appendChild( renderingModeElem );
QDomElement modelRenderingElem = doc.createElement( "modelRendering" );
QDomElement altitudeElem = doc.createElement( "altitude" );
altitudeElem.setAttribute( "clamping", config->altitudeClamping );
altitudeElem.setAttribute( "technique", config->altitudeTechnique );
altitudeElem.setAttribute( "binding", config->altitudeBinding );
altitudeElem.setAttribute( "verticalOffset", config->verticalOffset );
altitudeElem.setAttribute( "verticalScale", config->verticalScale );
altitudeElem.setAttribute( "clampingResolution", config->clampingResolution );
modelRenderingElem.appendChild( altitudeElem );
QDomElement extrusionElem = doc.createElement( "extrusion" );
extrusionElem.setAttribute( "enabled", config->extrusionEnabled );
extrusionElem.setAttribute( "height", config->extrusionHeight );
extrusionElem.setAttribute( "flatten", config->extrusionFlatten );
extrusionElem.setAttribute( "wall-gradient", config->extrusionWallGradient );
modelRenderingElem.appendChild( extrusionElem );
QDomElement labelingElem = doc.createElement( "labeling" );
labelingElem.setAttribute( "enabled", config->labelingEnabled );
labelingElem.setAttribute( "field", config->labelingField );
labelingElem.setAttribute( "declutter", config->labelingDeclutter );
modelRenderingElem.appendChild( labelingElem );
modelRenderingElem.setAttribute( "lighting", config->lightingEnabled );
globeElem.appendChild( modelRenderingElem );
elem.appendChild( globeElem );
}
}

View File

@ -0,0 +1,121 @@
/***************************************************************************
qgsglobevectorlayerproperties.h
--------------------------------------
Date : 9.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGLOBEVECTORLAYERPROPERTIES_H
#define QGSGLOBEVECTORLAYERPROPERTIES_H
#include "ui_qgsglobevectorlayerpropertiespage.h"
#include <qgsmaplayerpropertiesfactory.h>
#include <osgEarthSymbology/AltitudeSymbol>
class QgsGlobeVectorLayerConfig;
class QgsMapLayer;
class QDomDocument;
class QDomElement;
class QListWidgetItem;
struct QgsGlobeVectorLayerConfig : public QObject
{
public:
enum RenderingMode
{
RenderingModeRasterized,
RenderingModeModelSimple,
RenderingModeModelAdvanced
};
QgsGlobeVectorLayerConfig( QObject* parent = 0 )
: QObject( parent )
, renderingMode( RenderingModeRasterized )
, altitudeClamping( osgEarth::Symbology::AltitudeSymbol::CLAMP_TO_TERRAIN )
, altitudeTechnique( osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_DRAPE )
, altitudeBinding( osgEarth::Symbology::AltitudeSymbol::BINDING_VERTEX )
, verticalOffset( 0.0 )
, verticalScale( 0.0 )
, clampingResolution( 0.0 )
, extrusionEnabled( false )
, extrusionHeight( "10" )
, extrusionFlatten( false )
, extrusionWallGradient( 0.5 )
, labelingEnabled( false )
, labelingDeclutter( false )
, lightingEnabled( true )
{
}
RenderingMode renderingMode;
osgEarth::Symbology::AltitudeSymbol::Clamping altitudeClamping;
osgEarth::Symbology::AltitudeSymbol::Technique altitudeTechnique;
osgEarth::Symbology::AltitudeSymbol::Binding altitudeBinding;
float verticalOffset;
float verticalScale;
float clampingResolution;
bool extrusionEnabled;
QString extrusionHeight;
bool extrusionFlatten;
float extrusionWallGradient;
bool labelingEnabled;
QString labelingField;
bool labelingDeclutter;
bool lightingEnabled;
static QgsGlobeVectorLayerConfig* getConfig( QgsVectorLayer* layer );
};
class QgsGlobeVectorLayerPropertiesPage : public QgsVectorLayerPropertiesPage, private Ui::QgsGlobeVectorLayerPropertiesPage
{
Q_OBJECT
public:
explicit QgsGlobeVectorLayerPropertiesPage( QgsVectorLayer* layer, QWidget *parent = 0 );
public slots:
virtual void apply();
private slots:
void onAltitudeClampingChanged( int index );
void onAltituteTechniqueChanged( int index );
void showRenderingModeWidget( int index );
signals:
void layerSettingsChanged( QgsMapLayer* );
private:
QgsVectorLayer* mLayer;
};
class QgsGlobeLayerPropertiesFactory : public QObject, public QgsMapLayerPropertiesFactory
{
Q_OBJECT
public:
explicit QgsGlobeLayerPropertiesFactory( QObject* parent = 0 );
QgsVectorLayerPropertiesPage* createVectorLayerPropertiesPage( QgsVectorLayer* layer, QWidget* parent ) override;
QListWidgetItem* createVectorLayerPropertiesItem( QgsVectorLayer* layer, QListWidget* view ) override;
signals:
void layerSettingsChanged( QgsMapLayer* layer );
private slots:
void readGlobeVectorLayerConfig( QgsMapLayer* mapLayer, const QDomElement &elem );
void writeGlobeVectorLayerConfig( QgsMapLayer* mapLayer, QDomElement& elem, QDomDocument& doc );
};
#endif // QGSGLOBEVECTORLAYERPROPERTIES_H

View File

@ -0,0 +1,272 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsGlobeVectorLayerPropertiesPage</class>
<widget class="QgsVectorLayerPropertiesPage" name="QgsGlobeVectorLayerPropertiesPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>446</width>
<height>580</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QStackedWidget" name="stackedWidgetRenderingMode">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="pageRasterized">
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
<widget class="QWidget" name="pageModel">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBoxAltitude">
<property name="title">
<string>Altitude</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelAltitudeClamping">
<property name="toolTip">
<string>Terrain following behaviour</string>
</property>
<property name="text">
<string>Clamping</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxAltitudeClamping">
<property name="toolTip">
<string>Terrain following behavior</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelAltitudeTechnique">
<property name="toolTip">
<string>Terrain following technique</string>
</property>
<property name="text">
<string>Technique</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelAltitudeBinding">
<property name="toolTip">
<string>Granulatiry at which to sample the terrain</string>
</property>
<property name="text">
<string>Binding</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelAltitudeResolution">
<property name="toolTip">
<string>Elevation data resolution at which to sample terrain height</string>
</property>
<property name="text">
<string>Resolution</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelAltitudeOffset">
<property name="toolTip">
<string>Vertical offset to apply to geometry Z</string>
</property>
<property name="text">
<string>Offset</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelAltitudeScale">
<property name="toolTip">
<string>Scale factor to apply to geometry Z</string>
</property>
<property name="text">
<string>Scale</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBoxAltitudeTechnique">
<property name="toolTip">
<string>Terrain following technique</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxAltitudeBinding">
<property name="toolTip">
<string>Granulatiry at which to sample the terrain</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="spinBoxAltitudeResolution">
<property name="toolTip">
<string>Elevation data resolution at which to sample terrain height</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="spinBoxAltitudeOffset">
<property name="toolTip">
<string>Vertical offset to apply to geometry Z</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="spinBoxAltitudeScale">
<property name="toolTip">
<string>Scale factor to apply to geometry Z</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxExtrusion">
<property name="title">
<string>E&amp;xtrusion</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="labelExtrusionHeight_2">
<property name="text">
<string>Height [m]</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="labelExtrusionHeight">
<property name="toolTip">
<string>Extrusion height, either a numeric value, or a field expression</string>
</property>
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelExtrusionWallGradient">
<property name="text">
<string>Wall gradient</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="spinBoxExtrusionWallGradient">
<property name="toolTip">
<string>Wall coloring gradient</string>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.500000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxExtrusionFlatten">
<property name="toolTip">
<string>Whether the top cap of the extruded geometry should be flat</string>
</property>
<property name="text">
<string>Flatten</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxLabelingEnabled">
<property name="title">
<string>Enable &amp;labeling</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0">
<widget class="QCheckBox" name="checkBoxLabelingDeclutter">
<property name="text">
<string>Declutter</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxLighting">
<property name="text">
<string>Lighting</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelRenderingMode">
<property name="text">
<string>Rendering mode:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxRenderingMode">
<property name="toolTip">
<string>Rendering method for the layer</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsVectorLayerPropertiesPage</class>
<extends>QWidget</extends>
<header>qgsvectorlayerpropertiespage.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,153 @@
/***************************************************************************
qgsglobewidget.cpp
---------------------
begin : August 2010
copyright : (C) 2016 Sandro Mani
email : smani at sourcepole dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsglobewidget.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayer.h"
#include "qgsmaplayerregistry.h"
#include "qgsproject.h"
#include "qgsrasterlayer.h"
#include "qgisinterface.h"
#include "layertree/qgslayertree.h"
#include <QContextMenuEvent>
#include <QHBoxLayout>
#include <QLabel>
#include <QMenu>
#include <QToolButton>
QgsGlobeWidget::QgsGlobeWidget( QgisInterface* iface, QWidget *parent )
: QDockWidget( tr( "Globe" ), parent ), mQgisIface( iface )
{
setWindowTitle( tr( "Globe" ) );
QToolButton* layerSelectionButton = new QToolButton( this );
layerSelectionButton->setAutoRaise( true );
layerSelectionButton->setText( tr( "Layers" ) );
layerSelectionButton->setPopupMode( QToolButton::InstantPopup );
mLayerSelectionMenu = new QMenu( layerSelectionButton );
layerSelectionButton->setMenu( mLayerSelectionMenu );
QToolButton* syncButton = new QToolButton( this );
syncButton->setAutoRaise( true );
syncButton->setToolTip( tr( "Sync extent" ) );
syncButton->setIcon( QIcon( ":/images/themes/default/sync_views.svg" ) );
syncButton->setIconSize( QSize( 16, 16 ) );
connect( syncButton, SIGNAL( clicked() ), this, SIGNAL( syncExtent() ) );
QToolButton* refreshButton = new QToolButton( this );
refreshButton->setAutoRaise( true );
refreshButton->setToolTip( tr( "Reload scene" ) );
refreshButton->setIcon( QIcon( ":/images/themes/default/mActionRefresh.png" ) );
refreshButton->setIconSize( QSize( 16, 16 ) );
connect( refreshButton, SIGNAL( clicked() ), this, SIGNAL( refresh() ) );
QToolButton* settingsButton = new QToolButton( this );
settingsButton->setAutoRaise( true );
settingsButton->setToolTip( tr( "Globe settings" ) );
settingsButton->setIcon( QIcon( ":/images/themes/default/mActionOptions.svg" ) );
settingsButton->setIconSize( QSize( 16, 16 ) );
connect( settingsButton, SIGNAL( clicked() ), this, SIGNAL( showSettings() ) );
QToolButton* closeButton = new QToolButton( this );
closeButton->setAutoRaise( true );
closeButton->setIcon( QIcon( ":/images/themes/default/mActionRemove.svg" ) );
closeButton->setIconSize( QSize( 12, 12 ) );
closeButton->setToolTip( tr( "Close" ) );
connect( closeButton, SIGNAL( clicked( bool ) ), this, SLOT( deleteLater() ) );
QWidget* titleWidget = new QWidget( this );
titleWidget->setObjectName( "globeTitleWidget" );
titleWidget->setLayout( new QHBoxLayout() );
titleWidget->layout()->addWidget( layerSelectionButton );
titleWidget->layout()->addWidget( syncButton );
titleWidget->layout()->addWidget( refreshButton );
titleWidget->layout()->addWidget( settingsButton );
static_cast<QHBoxLayout*>( titleWidget->layout() )->addWidget( new QWidget( this ), 1 ); // spacer
titleWidget->layout()->addWidget( new QLabel( tr( "Globe" ) ) );
static_cast<QHBoxLayout*>( titleWidget->layout() )->addWidget( new QWidget( this ), 1 ); // spacer
titleWidget->layout()->addWidget( closeButton );
titleWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
setTitleBarWidget( titleWidget );
setMinimumSize( 128, 128 );
setAttribute( Qt::WA_DeleteOnClose );
connect( mQgisIface->mapCanvas(), SIGNAL( layersChanged() ), this, SLOT( updateLayerSelectionMenu() ) );
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersAdded( QList<QgsMapLayer*> ) ), this, SLOT( updateLayerSelectionMenu() ) );
connect( QgsMapLayerRegistry::instance(), SIGNAL( layerRemoved( QString ) ), this, SLOT( updateLayerSelectionMenu() ) );
updateLayerSelectionMenu();
}
void QgsGlobeWidget::updateLayerSelectionMenu()
{
QStringList prevLayers;
QStringList prevDisabledLayers;
QStringList prevEnabledLayers;
foreach ( QAction* action, mLayerSelectionMenu->actions() )
{
prevLayers.append( action->data().toString() );
if ( !action->isChecked() )
{
prevDisabledLayers.append( action->data().toString() );
}
else
{
prevEnabledLayers.append( action->data().toString() );
}
}
mLayerSelectionMenu->clear();
QString heightmap = QgsProject::instance()->readEntry( "Heightmap", "layer" );
// Use layerTreeRoot to get layers ordered as in the layer tree
foreach ( QgsLayerTreeLayer* layerTreeLayer, QgsProject::instance()->layerTreeRoot()->findLayers() )
{
QgsMapLayer* layer = layerTreeLayer->layer();
if ( !layer )
continue;
QAction* layerAction = new QAction( layer->name(), mLayerSelectionMenu );
layerAction->setData( layer->id() );
// Check if was not previously unchecked, unless it is a new layer with url=http in datasource
layerAction->setCheckable( true );
bool wasUnchecked = prevDisabledLayers.contains( layer->id() );
bool isNew = !prevLayers.contains( layer->id() );
bool isRemote = layer->source().contains( "url=http" );
bool isHeightmap = layer->id() == heightmap;
layerAction->setChecked( !wasUnchecked && !( isNew && ( isRemote || isHeightmap ) ) );
connect( layerAction, SIGNAL( toggled( bool ) ), this, SIGNAL( layersChanged() ) );
mLayerSelectionMenu->addAction( layerAction );
}
if ( prevEnabledLayers != getSelectedLayers() )
emit layersChanged();
}
QStringList QgsGlobeWidget::getSelectedLayers() const
{
QStringList selectedLayers;
foreach ( QAction* layerAction, mLayerSelectionMenu->actions() )
{
if ( layerAction->isChecked() )
{
selectedLayers.append( layerAction->data().toString() );
}
}
return selectedLayers;
}
void QgsGlobeWidget::contextMenuEvent( QContextMenuEvent * e )
{
e->accept();
}

View File

@ -0,0 +1,43 @@
/***************************************************************************
qgsglobewidget.h
---------------------
begin : August 2010
copyright : (C) 2016 Sandro Mani
email : smani at sourcepole dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QDockWidget>
class QgisInterface;
class QgsGlobePlugin;
class QMenu;
class QgsGlobeWidget : public QDockWidget
{
Q_OBJECT
public:
QgsGlobeWidget( QgisInterface *iface, QWidget* parent = 0 );
QStringList getSelectedLayers() const;
signals:
void layersChanged();
void showSettings();
void refresh();
void syncExtent();
private:
QgisInterface* mQgisIface;
QMenu* mLayerSelectionMenu;
void contextMenuEvent( QContextMenuEvent * e ) override;
private slots:
void updateLayerSelectionMenu();
};

View File

@ -1,225 +0,0 @@
/***************************************************************************
qgsosgearthtilesource.cpp
---------------------
begin : August 2010
copyright : (C) 2010 by Pirmin Kalberer
email : pka at sourcepole dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <osgEarth/TileSource>
#include <osgEarth/Registry>
#include <osgEarth/ImageUtils>
#include <osg/Notify>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include "qgsosgearthtilesource.h"
#include <qgsapplication.h>
#include <qgslogger.h>
#include <qgisinterface.h>
#include <qgsmapcanvas.h>
#ifdef USE_RENDERER
#include <qgsmaprenderer.h>
#else
#include <qgsmaprendererjob.h>
#endif
#include <QFile>
#include <QImage>
#include <QDesktopWidget>
using namespace osgEarth;
using namespace osgEarth::Drivers;
QgsOsgEarthTileSource::QgsOsgEarthTileSource( QgisInterface* theQgisInterface, const TileSourceOptions& options )
: TileSource( options )
, mQGisIface( theQgisInterface )
, mCoordTransform( 0 )
#ifdef USE_RENDERER
, mMapRenderer( 0 )
#endif
{
}
void QgsOsgEarthTileSource::initialize( const std::string& referenceURI, const Profile* overrideProfile )
{
Q_UNUSED( referenceURI );
Q_UNUSED( overrideProfile );
setProfile( osgEarth::Registry::instance()->getGlobalGeodeticProfile() );
QgsCoordinateReferenceSystem destCRS;
destCRS.createFromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
QgsMapCanvas *c = mQGisIface->mapCanvas();
if ( c->mapSettings().destinationCrs().authid().compare( GEO_EPSG_CRS_AUTHID, Qt::CaseInsensitive ) != 0 )
{
// FIXME: crs from canvas or first layer?
QgsCoordinateReferenceSystem srcCRS( c->mapSettings().destinationCrs() );
QgsDebugMsg( QString( "transforming from %1 to %2" ).arg( srcCRS.authid() ).arg( destCRS.authid() ) );
mCoordTransform = new QgsCoordinateTransform( srcCRS, destCRS );
}
else
{
mCoordTransform = 0;
}
#ifdef USE_RENDERER
mMapRenderer = new QgsMapRenderer();
mMapRenderer->setDestinationCrs( destCRS );
mMapRenderer->setProjectionsEnabled( true );
mMapRenderer->setOutputUnits( c->mapRenderer()->outputUnits() );
mMapRenderer->setMapUnits( QGis::Degrees );
#else
mMapSettings.setDestinationCrs( destCRS );
mMapSettings.setCrsTransformEnabled( true );
mMapSettings.setMapUnits( QGis::Degrees );
#endif
}
osg::Image* QgsOsgEarthTileSource::createImage( const TileKey& key, ProgressCallback* progress )
{
QString kname = key.str().c_str();
kname.replace( '/', '_' );
Q_UNUSED( progress );
//Get the extents of the tile
int tileSize = getPixelsPerTile();
if ( tileSize <= 0 )
{
QgsDebugMsg( "Tile size too small." );
return ImageUtils::createEmptyImage();
}
QgsRectangle viewExtent = mQGisIface->mapCanvas()->fullExtent();
if ( mCoordTransform )
{
QgsDebugMsg( QString( "vext0:%1" ).arg( viewExtent.toString( 5 ) ) );
viewExtent = mCoordTransform->transformBoundingBox( viewExtent );
}
QgsDebugMsg( QString( "vext1:%1" ).arg( viewExtent.toString( 5 ) ) );
double xmin, ymin, xmax, ymax;
key.getExtent().getBounds( xmin, ymin, xmax, ymax );
QgsRectangle tileExtent( xmin, ymin, xmax, ymax );
QgsDebugMsg( QString( "text0:%1" ).arg( tileExtent.toString( 5 ) ) );
if ( !viewExtent.intersects( tileExtent ) )
{
QgsDebugMsg( QString( "earth tile key:%1 ext:%2: NO INTERSECT" ).arg( kname ).arg( tileExtent.toString( 5 ) ) );
return ImageUtils::createEmptyImage();
}
#ifdef USE_RENDERER
QImage *qImage = createQImage( tileSize, tileSize );
if ( !qImage )
{
QgsDebugMsg( QString( "earth tile key:%1 ext:%2: EMPTY IMAGE" ).arg( kname ).arg( tileExtent.toString( 5 ) ) );
return ImageUtils::createEmptyImage();
}
mMapRenderer->setLayerSet( mQGisIface->mapCanvas()->mapRenderer()->layerSet() );
mMapRenderer->setOutputSize( QSize( tileSize, tileSize ), qImage->logicalDpiX() );
mMapRenderer->setExtent( tileExtent );
QPainter thePainter( qImage );
mMapRenderer->render( &thePainter );
#else
mMapSettings.setLayers( mQGisIface->mapCanvas()->mapSettings().layers() );
mMapSettings.setOutputSize( QSize( tileSize, tileSize ) );
mMapSettings.setOutputDpi( QgsApplication::desktop()->logicalDpiX() );
mMapSettings.setExtent( tileExtent );
mMapSettings.setBackgroundColor( QColor( 0, 0, 0, 0 ) );
QgsMapRendererSequentialJob job( mMapSettings );
job.start();
job.waitForFinished();
QImage *qImage = new QImage( job.renderedImage() );
if ( !qImage )
{
QgsDebugMsg( QString( "earth tile key:%1 ext:%2: EMPTY IMAGE" ).arg( kname ).arg( tileExtent.toString( 5 ) ) );
return ImageUtils::createEmptyImage();
}
Q_ASSERT( qImage->logicalDpiX() == QgsApplication::desktop()->logicalDpiX() );
Q_ASSERT( qImage->format() == QImage::Format_ARGB32_Premultiplied );
#endif
QgsDebugMsg( QString( "earth tile key:%1 ext:%2" ).arg( kname ).arg( tileExtent.toString( 5 ) ) );
#if 0
qImage->save( QString( "/tmp/tile-%1.png" ).arg( kname ) );
#endif
osg::ref_ptr<osg::Image> image = new osg::Image;
//The pixel format is always RGBA to support transparency
image->setImage( tileSize, tileSize, 1, 4, // width, height, depth, pixelFormat?
GL_BGRA, GL_UNSIGNED_BYTE, //Why not GL_RGBA - Qt bug?
qImage->bits(),
osg::Image::NO_DELETE, 1 );
image->flipVertical();
//Create a transparent image if we don't have an image
if ( !image.valid() )
{
QgsDebugMsg( "image is invalid" );
return ImageUtils::createEmptyImage();
}
QgsDebugMsg( "returning image" );
return image.release();
}
QImage* QgsOsgEarthTileSource::createQImage( int width, int height ) const
{
if ( width < 0 || height < 0 )
return 0;
QImage *qImage = 0;
//is format jpeg?
bool jpeg = false;
//transparent parameter
bool transparent = true;
//use alpha channel only if necessary because it slows down performance
if ( transparent && !jpeg )
{
qImage = new QImage( width, height, QImage::Format_ARGB32_Premultiplied );
qImage->fill( 0 );
}
else
{
qImage = new QImage( width, height, QImage::Format_RGB32 );
qImage->fill( qRgb( 255, 255, 255 ) );
}
if ( !qImage )
return 0;
//apply DPI parameter if present.
#if 0
int dpm = dpi / 0.0254;
qImage->setDotsPerMeterX( dpm );
qImage->setDotsPerMeterY( dpm );
#endif
return qImage;
}

View File

@ -1,86 +0,0 @@
/***************************************************************************
qgsosgearthtilesource.h
---------------------
begin : August 2010
copyright : (C) 2010 by Pirmin Kalberer
email : pka at sourcepole dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef OSGEARTH_DRIVER_QGIS_DRIVEROPTIONS
#define OSGEARTH_DRIVER_QGIS_DRIVEROPTIONS 1
#include <QtGlobal>
class QgisInterface;
class QgsMapRenderer;
class QgsCoordinateTransform;
class QImage;
#include <osgEarth/Common>
#include <osgEarth/TileSource>
#define USE_RENDERER
#ifndef USE_RENDERER
#include "qgsmapsettings.h"
#endif
using namespace osgEarth;
namespace osgEarth
{
namespace Drivers
{
class QgsOsgEarthTileSource : public TileSource
{
public:
QgsOsgEarthTileSource( QgisInterface* theQgisInterface, const TileSourceOptions& options = TileSourceOptions() );
void initialize( const std::string& referenceURI, const Profile* overrideProfile = nullptr );
osg::Image* createImage( const TileKey& key, ProgressCallback* progress ) override;
virtual osg::HeightField* createHeightField( const TileKey &key, ProgressCallback* progress ) override
{
Q_UNUSED( key );
Q_UNUSED( progress );
//NI
OE_WARN << "[QGIS] Driver does not support heightfields" << std::endl;
return nullptr;
}
virtual std::string getExtension() const override
{
//All QGIS tiles are in JPEG format
return "jpg";
}
virtual bool supportsPersistentCaching() const
{
return false;
}
private:
QImage* createQImage( int width, int height ) const;
//! Pointer to the QGIS interface object
QgisInterface *mQGisIface;
QgsCoordinateTransform *mCoordTransform;
#ifndef USE_RENDERER
QgsMapSettings mMapSettings;
#else
QgsMapRenderer *mMapRenderer;
#endif
};
}
} // namespace osgEarth::Drivers
#endif // OSGEARTH_DRIVER_QGIS_DRIVEROPTIONS

View File

@ -0,0 +1,20 @@
/***************************************************************************
qgsosgfeature.cpp
--------------------------------------
Date : 11.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsosgfeature.h"
QgsOsgFeature::QgsOsgFeature()
{
}

View File

@ -0,0 +1,25 @@
/***************************************************************************
qgsosgfeature.h
--------------------------------------
Date : 11.7.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSOSGFEATURE_H
#define QGSOSGFEATURE_H
class QgsOsgFeature : public Feature
{
public:
QgsOsgFeature();
};
#endif // QGSOSGFEATURE_H

View File

@ -458,7 +458,7 @@ QgsRectangle QgsInterpolationDialog::boundingBoxOfLayers()
}
else
{
combinedLayerExtent.combineExtentWith( &currentLayerExtent );
combinedLayerExtent.combineExtentWith( currentLayerExtent );
}
}
return combinedLayerExtent;

View File

@ -1171,7 +1171,7 @@ ErrorList topolTest::checkOverlapWithLayer( double tolerance, QgsVectorLayer* la
{
QgsRectangle r = bb;
QgsRectangle r2 = g2->boundingBox();
r.combineExtentWith( &r2 );
r.combineExtentWith( r2 );
QScopedPointer<QgsGeometry> conflictGeom( g1->intersection( g2 ) );
// could this for some reason return NULL?

View File

@ -474,7 +474,7 @@ void QgsDelimitedTextProvider::scanFile( bool buildIndexes )
mNumberFeatures++;
if ( geom->isMultipart() ) mWkbType = type;
QgsRectangle bbox( geom->boundingBox() );
mExtent.combineExtentWith( &bbox );
mExtent.combineExtentWith( bbox );
}
if ( buildSpatialIndex )
{
@ -797,7 +797,7 @@ void QgsDelimitedTextProvider::rescanFile()
else
{
QgsRectangle bbox( f.constGeometry()->boundingBox() );
mExtent.combineExtentWith( &bbox );
mExtent.combineExtentWith( bbox );
}
if ( buildSpatialIndex ) mSpatialIndex->insertFeature( f );
}

View File

@ -1256,7 +1256,7 @@ bool QgsWmsProvider::calculateExtent()
}
else
{
mLayerExtent.combineExtentWith( &extent );
mLayerExtent.combineExtentWith( extent );
}
firstLayer = false;

View File

@ -725,7 +725,7 @@ void QgsServerProjectParser::combineExtentAndCrsOfGroupChildren( QDomElement& gr
}
else
{
combinedBBox.combineExtentWith( &bbox );
combinedBBox.combineExtentWith( bbox );
}
}

Some files were not shown because too many files have changed in this diff Show More