[3d] missing piece of the jigsaw: save 3d canvas as image (#5927)

This commit is contained in:
Mathieu Pellerin 2017-12-21 16:16:20 +07:00 committed by GitHub
parent 909a0fc21c
commit 1ddcac501c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 0 deletions

View File

@ -17,6 +17,7 @@
#include <QBoxLayout>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DRender/QRenderCapture>
#include "qgscameracontroller.h"
#include "qgs3dmapsettings.h"
@ -27,6 +28,11 @@ Qgs3DMapCanvas::Qgs3DMapCanvas( QWidget *parent )
: QWidget( parent )
{
mWindow3D = new Qt3DExtras::Qt3DWindow;
mCapture = new Qt3DRender::QRenderCapture;
mWindow3D->activeFrameGraph()->setParent( mCapture );
mWindow3D->setActiveFrameGraph( mCapture );
mContainer = QWidget::createWindowContainer( mWindow3D );
QHBoxLayout *hLayout = new QHBoxLayout( this );
@ -89,3 +95,19 @@ void Qgs3DMapCanvas::setViewFromTop( const QgsPointXY &center, float distance, f
float worldY = center.y() - mMap->origin().y();
mScene->cameraController()->setViewFromTop( worldX, -worldY, distance, rotation );
}
void Qgs3DMapCanvas::saveAsImage( const QString fileName, const QString fileFormat )
{
if ( !fileName.isEmpty() )
{
Qt3DRender::QRenderCaptureReply *captureReply;
captureReply = mCapture->requestCapture();
connect( captureReply, &Qt3DRender::QRenderCaptureReply::completed, this, [ = ]
{
captureReply->image().save( fileName, fileFormat.toLocal8Bit().data() );
emit savedAsImage( fileName );
captureReply->deleteLater();
} );
}
}

View File

@ -17,6 +17,7 @@
#define QGS3DMAPCANVAS_H
#include <QWidget>
#include <Qt3DRender/QRenderCapture>
namespace Qt3DExtras
{
@ -54,12 +55,22 @@ class Qgs3DMapCanvas : public QWidget
//! Sets camera position to look down at the given point (in map coordinates) in given distance from plane with zero elevation
void setViewFromTop( const QgsPointXY &center, float distance, float rotation = 0 );
//! Saves the current scene as an image
void saveAsImage( const QString fileName, const QString fileFormat );
signals:
//! Emitted when the 3D map canvas was successfully saved as image
void savedAsImage( const QString fileName );
protected:
void resizeEvent( QResizeEvent *ev ) override;
private:
//! 3D window with all the 3D magic inside
Qt3DExtras::Qt3DWindow *mWindow3D = nullptr;
//! Frame graph node for render capture
Qt3DRender::QRenderCapture *mCapture = nullptr;
//! Container QWidget that encapsulates mWindow3D so we can use it embedded in ordinary widgets app
QWidget *mContainer = nullptr;
//! Description of the 3D scene

View File

@ -30,6 +30,7 @@
#include <QDialogButtonBox>
#include <QProgressBar>
#include <QToolBar>
#include <QUrl>
Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
: QgsDockWidget( parent )
@ -42,6 +43,8 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
toolBar->setIconSize( QgisApp::instance()->iconSize( true ) );
toolBar->addAction( QgsApplication::getThemeIcon( QStringLiteral( "mActionZoomFullExtent.svg" ) ),
tr( "Zoom Full" ), this, &Qgs3DMapCanvasDockWidget::resetView );
toolBar->addAction( QgsApplication::getThemeIcon( QStringLiteral( "mActionSaveMapAsImage.svg" ) ),
tr( "Save as image..." ), this, &Qgs3DMapCanvasDockWidget::saveAsImage );
toolBar->addAction( QgsApplication::getThemeIcon( QStringLiteral( "mIconProperties.svg" ) ),
tr( "Configure" ), this, &Qgs3DMapCanvasDockWidget::configure );
@ -49,6 +52,11 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
mCanvas->setMinimumSize( QSize( 200, 200 ) );
mCanvas->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
connect( mCanvas, &Qgs3DMapCanvas::savedAsImage, this, [ = ]( const QString fileName )
{
QgisApp::instance()->messageBar()->pushSuccess( tr( "Save as Image" ), tr( "Successfully saved the 3D map to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( QFileInfo( fileName ).path() ).toString(), fileName ) );
} );
mLabelPendingJobs = new QLabel( this );
mProgressPendingJobs = new QProgressBar( this );
mProgressPendingJobs->setRange( 0, 0 );
@ -74,6 +82,15 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
onTerrainPendingJobsCountChanged();
}
void Qgs3DMapCanvasDockWidget::saveAsImage()
{
QPair< QString, QString> fileNameAndFilter = QgsGuiUtils::getSaveAsImageName( this, tr( "Choose a file name to save the 3D map canvas to an image" ) );
if ( !fileNameAndFilter.first.isEmpty() )
{
mCanvas->saveAsImage( fileNameAndFilter.first, fileNameAndFilter.second );
}
}
void Qgs3DMapCanvasDockWidget::setMapSettings( Qgs3DMapSettings *map )
{
mCanvas->setMap( map );

View File

@ -42,6 +42,7 @@ class Qgs3DMapCanvasDockWidget : public QgsDockWidget
private slots:
void resetView();
void configure();
void saveAsImage();
void onMainCanvasLayersChanged();
void onMainCanvasColorChanged();