QGIS API Documentation  3.0.2-Girona (307d082)
qgsterrainentity_p.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsterrainentity_p.cpp
3  --------------------------------------
4  Date : July 2017
5  Copyright : (C) 2017 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsterrainentity_p.h"
17 
18 #include "qgsaabb.h"
19 #include "qgs3dmapsettings.h"
20 #include "qgschunknode_p.h"
21 #include "qgsterraingenerator.h"
24 #include "qgsterraintileentity_p.h"
25 
26 #include "qgscoordinatetransform.h"
27 
28 #include <Qt3DRender/QObjectPicker>
29 
30 
32 
34 class TerrainMapUpdateJobFactory : public QgsChunkQueueJobFactory
35 {
36  public:
37  TerrainMapUpdateJobFactory( QgsTerrainTextureGenerator *textureGenerator )
38  : mTextureGenerator( textureGenerator )
39  {
40  }
41 
42  QgsChunkQueueJob *createJob( QgsChunkNode *chunk ) override
43  {
44  return new TerrainMapUpdateJob( mTextureGenerator, chunk );
45  }
46 
47  private:
48  QgsTerrainTextureGenerator *mTextureGenerator = nullptr;
49 };
50 
51 
52 // -----------
53 
54 
55 QgsTerrainEntity::QgsTerrainEntity( int maxLevel, const Qgs3DMapSettings &map, Qt3DCore::QNode *parent )
56  : QgsChunkedEntity( map.terrainGenerator()->rootChunkBbox( map ),
57  map.terrainGenerator()->rootChunkError( map ),
58  map.maxTerrainScreenError(), maxLevel, map.terrainGenerator(), parent )
59  , mMap( map )
60 {
61  map.terrainGenerator()->setTerrain( this );
62 
63  connect( &map, &Qgs3DMapSettings::showTerrainBoundingBoxesChanged, this, &QgsTerrainEntity::onShowBoundingBoxesChanged );
64  connect( &map, &Qgs3DMapSettings::showTerrainTilesInfoChanged, this, &QgsTerrainEntity::invalidateMapImages );
65  connect( &map, &Qgs3DMapSettings::showLabelsChanged, this, &QgsTerrainEntity::invalidateMapImages );
66  connect( &map, &Qgs3DMapSettings::layersChanged, this, &QgsTerrainEntity::onLayersChanged );
67  connect( &map, &Qgs3DMapSettings::backgroundColorChanged, this, &QgsTerrainEntity::invalidateMapImages );
68 
69  connectToLayersRepaintRequest();
70 
71  mTerrainToMapTransform = new QgsCoordinateTransform( map.terrainGenerator()->crs(), map.crs(), map.transformContext() );
72 
73  mTextureGenerator = new QgsTerrainTextureGenerator( map );
74 
75  mUpdateJobFactory.reset( new TerrainMapUpdateJobFactory( mTextureGenerator ) );
76 
77  mTerrainPicker = new Qt3DRender::QObjectPicker;
78  // add camera control's terrain picker as a component to be able to capture height where mouse was
79  // pressed in order to correcly pan camera when draggin mouse
80  addComponent( mTerrainPicker );
81 }
82 
83 QgsTerrainEntity::~QgsTerrainEntity()
84 {
85  // cancel / wait for jobs
86  if ( mActiveJob )
87  cancelActiveJob();
88 
89  delete mTextureGenerator;
90  delete mTerrainToMapTransform;
91 }
92 
93 void QgsTerrainEntity::onShowBoundingBoxesChanged()
94 {
95  setShowBoundingBoxes( mMap.showTerrainBoundingBoxes() );
96 }
97 
98 
99 void QgsTerrainEntity::invalidateMapImages()
100 {
101  // handle active nodes
102 
103  updateNodes( mActiveNodes, mUpdateJobFactory.get() );
104 
105  // handle inactive nodes afterwards
106 
107  QList<QgsChunkNode *> inactiveNodes;
108  Q_FOREACH ( QgsChunkNode *node, mRootNode->descendants() )
109  {
110  if ( !node->entity() )
111  continue;
112  if ( mActiveNodes.contains( node ) )
113  continue;
114  inactiveNodes << node;
115  }
116 
117  updateNodes( inactiveNodes, mUpdateJobFactory.get() );
118 
119  setNeedsUpdate( true );
120 }
121 
122 void QgsTerrainEntity::onLayersChanged()
123 {
124  connectToLayersRepaintRequest();
125  invalidateMapImages();
126 }
127 
128 void QgsTerrainEntity::connectToLayersRepaintRequest()
129 {
130  Q_FOREACH ( QgsMapLayer *layer, mLayers )
131  {
132  disconnect( layer, &QgsMapLayer::repaintRequested, this, &QgsTerrainEntity::invalidateMapImages );
133  }
134 
135  mLayers = mMap.layers();
136 
137  Q_FOREACH ( QgsMapLayer *layer, mLayers )
138  {
139  connect( layer, &QgsMapLayer::repaintRequested, this, &QgsTerrainEntity::invalidateMapImages );
140  }
141 }
142 
143 
144 // -----------
145 
146 
147 TerrainMapUpdateJob::TerrainMapUpdateJob( QgsTerrainTextureGenerator *textureGenerator, QgsChunkNode *node )
148  : QgsChunkQueueJob( node )
149  , mTextureGenerator( textureGenerator )
150 {
151  QgsTerrainTileEntity *entity = qobject_cast<QgsTerrainTileEntity *>( node->entity() );
152  connect( textureGenerator, &QgsTerrainTextureGenerator::tileReady, this, &TerrainMapUpdateJob::onTileReady );
153  mJobId = textureGenerator->render( entity->textureImage()->imageExtent(), entity->textureImage()->imageDebugText() );
154 }
155 
156 void TerrainMapUpdateJob::cancel()
157 {
158  if ( mJobId != -1 )
159  mTextureGenerator->cancelJob( mJobId );
160 }
161 
162 
163 void TerrainMapUpdateJob::onTileReady( int jobId, const QImage &image )
164 {
165  if ( mJobId == jobId )
166  {
167  QgsTerrainTileEntity *entity = qobject_cast<QgsTerrainTileEntity *>( mNode->entity() );
168  entity->textureImage()->setImage( image );
169  mJobId = -1;
170  emit finished();
171  }
172 }
173 
Base class for all map layer types.
Definition: qgsmaplayer.h:56
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used in the 3D scene.
void layersChanged()
Emitted when the list of map layers for terrain texture has changed.
QgsCoordinateReferenceSystem crs() const
Returns CRS of the terrain.
3 Definition of the world
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
void showTerrainBoundingBoxesChanged()
Emitted when the flag whether terrain&#39;s bounding boxes are shown has changed.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
void showTerrainTilesInfoChanged()
Emitted when the flag whether terrain&#39;s tile info is shown has changed.
void showLabelsChanged()
Emitted when the flag whether labels are displayed on terrain tiles has changed.
Class for doing transforms between two map coordinate systems.
void setTerrain(QgsTerrainEntity *t)
Sets terrain entity for the generator (does not transfer ownership)
void backgroundColorChanged()
Emitted when the background color has changed.
QgsTerrainGenerator * terrainGenerator() const
Returns terrain generator. It takes care of producing terrain tiles from the input data...