31#include <Qt3DCore/QAspectEngine>
32#include <Qt3DCore/QCoreAspect>
33#include <Qt3DInput/QInputAspect>
34#include <Qt3DInput/QInputSettings>
35#include <Qt3DLogic/QFrameAction>
36#include <Qt3DLogic/QLogicAspect>
37#include <Qt3DRender/QRenderAspect>
38#include <Qt3DRender/QRenderSettings>
40#include "moc_qgs3dmapcanvas.cpp"
42using namespace Qt::StringLiterals;
45 : m_aspectEngine( new
Qt3DCore::QAspectEngine )
46 , m_renderAspect( new
Qt3DRender::QRenderAspect )
47 , m_inputAspect( new
Qt3DInput::QInputAspect )
48 , m_logicAspect( new
Qt3DLogic::QLogicAspect )
49 , m_renderSettings( new
Qt3DRender::QRenderSettings )
51 , m_inputSettings( new
Qt3DInput::QInputSettings )
54 setSurfaceType( QSurface::OpenGLSurface );
57 m_aspectEngine->registerAspect(
new Qt3DCore::QCoreAspect );
58 m_aspectEngine->registerAspect( m_renderAspect );
59 m_aspectEngine->registerAspect( m_inputAspect );
60 m_aspectEngine->registerAspect( m_logicAspect );
62 m_defaultCamera->setParent( m_root );
63 m_inputSettings->setEventSource(
this );
69 if ( image.save( mCaptureFileName, mCaptureFileFormat.toLocal8Bit().data() ) )
75 setCursor( Qt::OpenHandCursor );
76 installEventFilter(
this );
84 mScene->deleteLater();
86 mMapSettings->deleteLater();
87 mMapSettings =
nullptr;
89 delete m_aspectEngine;
94 if ( m_userRoot != root )
97 m_userRoot->setParent(
static_cast<Qt3DCore::QNode *
>(
nullptr ) );
99 root->setParent( m_root );
111 return m_renderSettings->activeFrameGraph();
116 return m_defaultCamera;
121 return m_renderSettings;
126 if ( !m_initialized )
128 m_root->addComponent( m_renderSettings );
129 m_root->addComponent( m_inputSettings );
130 m_aspectEngine->setRootEntity( Qt3DCore::QEntityPtr( m_root ) );
132 m_initialized =
true;
134 QWindow::showEvent( e );
139 m_defaultCamera->setAspectRatio(
float( width() ) / std::max( 1.f,
static_cast<float>( height() ) ) );
141 mEngine->setSize( size() );
147 Q_ASSERT( !mMapSettings );
152 mEngine->setSize( size() );
153 mEngine->setRootEntity( newScene );
157 mScene->deleteLater();
184 return mScene ? mScene->cameraController() :
nullptr;
203 if ( !mCrossSection.isValid() )
205 mScene->disableClipping();
210 const QgsPoint startPoint = mCrossSection.startPoint();
211 const QgsPoint endPoint = mCrossSection.endPoint();
212 const double width = mCrossSection.halfWidth();
214 const QgsVector3D startVec { startPoint.
x(), startPoint.
y(), 0 };
218 mScene->enableClipping( clippingPlanes );
225 return mScene ? !mScene->clipPlaneEquations().isEmpty() :
false;
233 mScene->viewZoomFull();
241 const float worldX = center.
x() - mMapSettings->origin().x();
242 const float worldY = center.
y() - mMapSettings->origin().y();
243 mScene->cameraController()->setViewFromTop( worldX, worldY, distance, rotation );
248 if ( !mScene || fileName.isEmpty() )
251 mCaptureFileName = fileName;
252 mCaptureFileFormat = fileFormat;
254 Qt3DLogic::QFrameAction *screenCaptureFrameAction =
new Qt3DLogic::QFrameAction;
255 mScene->addComponent( screenCaptureFrameAction );
257 connect( screenCaptureFrameAction, &Qt3DLogic::QFrameAction::triggered,
this, [
this, screenCaptureFrameAction](
float ) {
258 mEngine->requestCaptureImage();
259 mScene->removeComponent( screenCaptureFrameAction );
260 screenCaptureFrameAction->deleteLater();
264void Qgs3DMapCanvas::captureDepthBuffer()
270 Qt3DLogic::QFrameAction *screenCaptureFrameAction =
new Qt3DLogic::QFrameAction;
271 mScene->addComponent( screenCaptureFrameAction );
273 connect( screenCaptureFrameAction, &Qt3DLogic::QFrameAction::triggered,
this, [
this, screenCaptureFrameAction](
float ) {
275 mScene->removeComponent( screenCaptureFrameAction );
276 screenCaptureFrameAction->deleteLater();
285 if ( tool == mMapTool )
289 if ( mMapTool && !tool )
291 mScene->cameraController()->setEnabled(
true );
292 setCursor( Qt::OpenHandCursor );
296 mMapTool->deactivate();
302 mMapTool->activate();
303 setCursor( mMapTool->cursor() );
309 if ( watched !=
this )
312 if ( mScene && mScene->get3DAxis() && mScene->get3DAxis()->handleEvent( event ) )
321 if ( event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease || event->type() == QEvent::ShortcutOverride )
337 switch ( event->type() )
339 case QEvent::MouseButtonPress:
340 mMapTool->mousePressEvent(
static_cast<QMouseEvent *
>( event ) );
342 case QEvent::MouseButtonRelease:
343 mMapTool->mouseReleaseEvent(
static_cast<QMouseEvent *
>( event ) );
345 case QEvent::MouseMove:
346 mMapTool->mouseMoveEvent(
static_cast<QMouseEvent *
>( event ) );
348 case QEvent::KeyPress:
349 mMapTool->keyPressEvent(
static_cast<QKeyEvent *
>( event ) );
351 case QEvent::KeyRelease:
352 mMapTool->keyReleaseEvent(
static_cast<QKeyEvent *
>( event ) );
355 mMapTool->mouseWheelEvent(
static_cast<QWheelEvent *
>( event ) );
365 if ( mTemporalController )
368 mTemporalController = temporalController;
372void Qgs3DMapCanvas::updateTemporalRange(
const QgsDateTimeRange &temporalrange )
383 mMapSettings->setCameraNavigationMode( mode );
391 mScene->setViewFrom2DExtent( extent );
396 return mScene ? mScene->viewFrustum2DExtent() : QVector<QgsPointXY>();
401 mHighlightsHandler->highlightFeature( feature, layer );
406 mHighlightsHandler->clearHighlights();
NavigationMode
The navigation mode used by 3D cameras.
Handles the creation of 3D entities used for highlighting identified features.
void saveAsImage(const QString &fileName, const QString &fileFormat)
Saves the current scene as an image.
QVector< QgsPointXY > viewFrustum2DExtent()
Calculates the 2D extent viewed by the 3D camera as the vertices of the viewed trapezoid.
Qgs3DMapSettings * mapSettings()
Returns access to the 3D scene configuration.
void setTemporalController(QgsTemporalController *temporalController)
Sets the temporal controller.
bool crossSectionEnabled() const
Returns true if the cross section mode is enabled or the 3d scene has other clipping planes applied.
void mapSettingsChanged()
Emitted when the the map setting is changed.
void crossSectionEnabledChanged(bool enabled)
Emitted when the cross section mode is enabled or disabled.
Qt3DRender::QCamera * camera() const
Returns the default camera of the 3D Window.
void viewed2DExtentFrom3DChanged(QVector< QgsPointXY > extent)
Emitted when the viewed 2D extent seen by the 3D camera has changed.
void fpsCountChanged(float fpsCount)
Emitted when the FPS count changes (at most every frame).
void setRootEntity(Qt3DCore::QEntity *root)
Sets the specified root entity of the scene.
void setViewFromTop(const QgsPointXY ¢er, float distance, float rotation=0)
Sets camera position to look down at the given point (in map coordinates) in given distance from plan...
void setActiveFrameGraph(Qt3DRender::QFrameGraphNode *activeFrameGraph)
Activates the specified activeFrameGraph.
void setMapSettings(Qgs3DMapSettings *mapSettings)
Configure map scene being displayed. Takes ownership.
void showEvent(QShowEvent *e) override
Manages the display events specified in e.
QgsCrossSection crossSection() const
Returns the current cross section definition for the 3D map canvas.
void cameraNavigationSpeedChanged(double speed)
Emitted when the camera navigation speed is changed.
Qt3DRender::QRenderSettings * renderSettings() const
Returns the render settings of the 3D Window.
~Qgs3DMapCanvas() override
Qt3DRender::QFrameGraphNode * activeFrameGraph() const
Returns the node of the active frame graph.
void setMapTool(Qgs3DMapTool *tool)
Sets the active map tool that will receive events from the 3D canvas.
void setViewFrom2DExtent(const QgsRectangle &extent)
Resets camera view to show the extent (top view).
QgsRayCastResult castRay(const QPoint &screenPoint, QgsRayCastContext context)
Casts a ray towards the 3d scene and returns information about the intersected 3d entities.
void resizeEvent(QResizeEvent *) override
Resets the aspect ratio of the 3D window.
void highlightFeature(const QgsFeature &feature, QgsMapLayer *layer)
Add a highlight 3d entity for feature of layer.
void resetView()
Resets camera position to the default: looking down at the origin of world coordinates.
void savedAsImage(const QString &fileName)
Emitted when the 3D map canvas was successfully saved as image.
void clearHighlights()
Removes all highlight entities.
void setCrossSection(const QgsCrossSection &crossSection)
Sets the cross section definition for the 3D map canvas.
void fpsCounterEnabledChanged(bool enabled)
Emitted when the FPS counter is enabled or disabeld.
QgsCameraController * cameraController()
Returns access to the view's camera controller. Returns nullptr if the scene has not been initialized...
bool eventFilter(QObject *watched, QEvent *event) override
Entity that encapsulates our 3D scene - contains all other entities (such as terrain) as children.
void viewed2DExtentFrom3DChanged(QVector< QgsPointXY > extent)
Emitted when the viewed 2D extent seen by the 3D camera has changed.
void fpsCountChanged(float fpsCount)
Emitted when the FPS count changes.
void updateTemporal()
Updates the temporale entities.
void fpsCounterEnabledChanged(bool fpsCounterEnabled)
Emitted when the FPS counter is activated or deactivated.
void setCameraMovementSpeed(double movementSpeed)
Sets the camera movement speed.
static QList< QVector4D > lineSegmentToClippingPlanes(const QgsVector3D &startPoint, const QgsVector3D &endPoint, double distance, const QgsVector3D &origin)
Returns a list of 4 planes derived from a line extending from startPoint to endPoint.
static QgsRayCastResult castRay(Qgs3DMapScene *scene, const QgsRay3D &ray, const QgsRayCastContext &context)
Casts a ray through the scene and returns information about the intersecting entities (ray uses World...
static QgsRay3D rayFromScreenPoint(const QPoint &point, const QSize &windowSize, Qt3DRender::QCamera *camera)
Convert from clicked point on the screen to a ray in world coordinates.
void requestDepthBufferCapture()
Starts a request for an image containing the depth buffer data of the engine.
void imageCaptured(const QImage &image)
Emitted after a call to requestCaptureImage() to return the captured image.
void depthBufferCaptured(const QImage &image)
Emitted after a call to requestDepthBufferCapture() to return the captured depth buffer.
Object that controls camera movement based on user input.
void navigationModeChanged(Qgis::NavigationMode mode)
Emitted when the navigation mode is changed using the hotkey ctrl + ~.
void requestDepthBufferCapture()
Emitted to ask for the depth buffer image.
void cameraMovementSpeedChanged(double speed)
Emitted whenever the camera movement speed is changed by the controller.
void depthBufferCaptured(const QImage &depthImage)
Sets the depth buffer image used by the camera controller to calculate world position from a pixel's ...
void setCursorPosition(QPoint point)
Emitted when the mouse cursor position should be moved to the specified point on the map viewport.
Encapsulates the definition of a cross section in 3D map coordinates.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Base class for all map layer types.
Point geometry type, with support for z-dimension and m-values.
A representation of a ray in 3D.
Responsible for defining parameters of the ray casting operations in 3D map canvases.
float maximumDistance() const
The maximum distance from ray origin to look for hits when casting a ray.
void setMaximumDistance(float distance)
Sets the maximum distance from ray origin to look for hits when casting a ray.
Contains the results of ray casting operations in a 3D map canvas.
A rectangle specified with double values.
Stores settings for use within QGIS.
A controller base class for temporal objects, contains a signal for notifying updates of the objects ...
void updateTemporalRange(const QgsDateTimeRange &range)
Signals that a temporal range has changed and needs to be updated in all connected objects.
void setTemporalRange(const QgsDateTimeRange &range)
Sets the temporal range for the object.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
On-screen 3D engine: it creates an OpenGL window (QWindow) and displays rendered 3D scenes there.
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.