QGIS API Documentation  3.2.0-Bonn (bc43194)
qgs3dmapsettings.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgs3dmapsettings.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 "qgs3dmapsettings.h"
17 
19 #include "qgsdemterraingenerator.h"
20 //#include "quantizedmeshterraingenerator.h"
22 
23 #include <QDomDocument>
24 #include <QDomElement>
25 
26 #include "qgssymbollayerutils.h"
27 #include "qgsrasterlayer.h"
28 
30  : QObject( nullptr )
31  , mOrigin( other.mOrigin )
32  , mCrs( other.mCrs )
33  , mBackgroundColor( other.mBackgroundColor )
34  , mTerrainVerticalScale( other.mTerrainVerticalScale )
35  , mTerrainGenerator( other.mTerrainGenerator ? other.mTerrainGenerator->clone() : nullptr )
36  , mMapTileResolution( other.mMapTileResolution )
37  , mMaxTerrainScreenError( other.mMaxTerrainScreenError )
38  , mMaxTerrainGroundError( other.mMaxTerrainGroundError )
39  , mShowTerrainBoundingBoxes( other.mShowTerrainBoundingBoxes )
40  , mShowTerrainTileInfo( other.mShowTerrainTileInfo )
41  , mLayers( other.mLayers )
42  , mSkyboxEnabled( other.mSkyboxEnabled )
43  , mSkyboxFileBase( other.mSkyboxFileBase )
44  , mSkyboxFileExtension( other.mSkyboxFileExtension )
45 {
46  Q_FOREACH ( QgsAbstract3DRenderer *renderer, other.mRenderers )
47  {
48  mRenderers << renderer->clone();
49  }
50 }
51 
53 {
54  qDeleteAll( mRenderers );
55 }
56 
57 void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
58 {
59  QDomElement elemOrigin = elem.firstChildElement( "origin" );
60  mOrigin = QgsVector3D(
61  elemOrigin.attribute( "x" ).toDouble(),
62  elemOrigin.attribute( "y" ).toDouble(),
63  elemOrigin.attribute( "z" ).toDouble() );
64 
65  QDomElement elemCrs = elem.firstChildElement( "crs" );
66  mCrs.readXml( elemCrs );
67 
68  QDomElement elemTerrain = elem.firstChildElement( "terrain" );
69  mTerrainVerticalScale = elemTerrain.attribute( "exaggeration", "1" ).toFloat();
70  mMapTileResolution = elemTerrain.attribute( "texture-size", "512" ).toInt();
71  mMaxTerrainScreenError = elemTerrain.attribute( "max-terrain-error", "3" ).toFloat();
72  mMaxTerrainGroundError = elemTerrain.attribute( "max-ground-error", "1" ).toFloat();
73  mShowLabels = elemTerrain.attribute( "show-labels", "0" ).toInt();
74  QDomElement elemMapLayers = elemTerrain.firstChildElement( "layers" );
75  QDomElement elemMapLayer = elemMapLayers.firstChildElement( "layer" );
76  QList<QgsMapLayerRef> mapLayers;
77  while ( !elemMapLayer.isNull() )
78  {
79  mapLayers << QgsMapLayerRef( elemMapLayer.attribute( "id" ) );
80  elemMapLayer = elemMapLayer.nextSiblingElement( "layer" );
81  }
82  mLayers = mapLayers; // needs to resolve refs afterwards
83  QDomElement elemTerrainGenerator = elemTerrain.firstChildElement( "generator" );
84  QString terrainGenType = elemTerrainGenerator.attribute( "type" );
85  if ( terrainGenType == "dem" )
86  {
87  QgsDemTerrainGenerator *demTerrainGenerator = new QgsDemTerrainGenerator;
88  demTerrainGenerator->setCrs( mCrs, mTransformContext );
89  mTerrainGenerator.reset( demTerrainGenerator );
90  }
91  else if ( terrainGenType == "quantized-mesh" )
92  {
93 #if 0
95 #endif
96  Q_ASSERT( false ); // currently disabled
97  }
98  else // "flat"
99  {
101  flatGen->setCrs( mCrs );
102  mTerrainGenerator.reset( flatGen );
103  }
104  mTerrainGenerator->readXml( elemTerrainGenerator );
105 
106  qDeleteAll( mRenderers );
107  mRenderers.clear();
108 
109  QDomElement elemRenderers = elem.firstChildElement( "renderers" );
110  QDomElement elemRenderer = elemRenderers.firstChildElement( "renderer" );
111  while ( !elemRenderer.isNull() )
112  {
113  QgsAbstract3DRenderer *renderer = nullptr;
114  QString type = elemRenderer.attribute( "type" );
115  if ( type == "vector" )
116  {
117  renderer = new QgsVectorLayer3DRenderer;
118  }
119 
120  if ( renderer )
121  {
122  renderer->readXml( elemRenderer, context );
123  mRenderers.append( renderer );
124  }
125  elemRenderer = elemRenderer.nextSiblingElement( "renderer" );
126  }
127 
128  QDomElement elemSkybox = elem.firstChildElement( "skybox" );
129  mSkyboxEnabled = elemSkybox.attribute( "enabled", "0" ).toInt();
130  mSkyboxFileBase = elemSkybox.attribute( "file-base" );
131  mSkyboxFileExtension = elemSkybox.attribute( "file-ext" );
132 
133  QDomElement elemDebug = elem.firstChildElement( "debug" );
134  mShowTerrainBoundingBoxes = elemDebug.attribute( "bounding-boxes", "0" ).toInt();
135  mShowTerrainTileInfo = elemDebug.attribute( "terrain-tile-info", "0" ).toInt();
136 }
137 
138 QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
139 {
140  QDomElement elem = doc.createElement( "qgis3d" );
141 
142  QDomElement elemOrigin = doc.createElement( "origin" );
143  elemOrigin.setAttribute( "x", QString::number( mOrigin.x() ) );
144  elemOrigin.setAttribute( "y", QString::number( mOrigin.y() ) );
145  elemOrigin.setAttribute( "z", QString::number( mOrigin.z() ) );
146  elem.appendChild( elemOrigin );
147 
148  QDomElement elemCrs = doc.createElement( "crs" );
149  mCrs.writeXml( elemCrs, doc );
150  elem.appendChild( elemCrs );
151 
152  QDomElement elemTerrain = doc.createElement( "terrain" );
153  elemTerrain.setAttribute( "exaggeration", QString::number( mTerrainVerticalScale ) );
154  elemTerrain.setAttribute( "texture-size", mMapTileResolution );
155  elemTerrain.setAttribute( "max-terrain-error", QString::number( mMaxTerrainScreenError ) );
156  elemTerrain.setAttribute( "max-ground-error", QString::number( mMaxTerrainGroundError ) );
157  elemTerrain.setAttribute( "show-labels", mShowLabels ? 1 : 0 );
158  QDomElement elemMapLayers = doc.createElement( "layers" );
159  Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers )
160  {
161  QDomElement elemMapLayer = doc.createElement( "layer" );
162  elemMapLayer.setAttribute( "id", layerRef.layerId );
163  elemMapLayers.appendChild( elemMapLayer );
164  }
165  elemTerrain.appendChild( elemMapLayers );
166  QDomElement elemTerrainGenerator = doc.createElement( "generator" );
167  elemTerrainGenerator.setAttribute( "type", QgsTerrainGenerator::typeToString( mTerrainGenerator->type() ) );
168  mTerrainGenerator->writeXml( elemTerrainGenerator );
169  elemTerrain.appendChild( elemTerrainGenerator );
170  elem.appendChild( elemTerrain );
171 
172  QDomElement elemRenderers = doc.createElement( "renderers" );
173  Q_FOREACH ( const QgsAbstract3DRenderer *renderer, mRenderers )
174  {
175  QDomElement elemRenderer = doc.createElement( "renderer" );
176  elemRenderer.setAttribute( "type", renderer->type() );
177  renderer->writeXml( elemRenderer, context );
178  elemRenderers.appendChild( elemRenderer );
179  }
180  elem.appendChild( elemRenderers );
181 
182  QDomElement elemSkybox = doc.createElement( "skybox" );
183  elemSkybox.setAttribute( "enabled", mSkyboxEnabled ? 1 : 0 );
184  // TODO: use context for relative paths, maybe explicitly list all files(?)
185  elemSkybox.setAttribute( "file-base", mSkyboxFileBase );
186  elemSkybox.setAttribute( "file-ext", mSkyboxFileExtension );
187  elem.appendChild( elemSkybox );
188 
189  QDomElement elemDebug = doc.createElement( "debug" );
190  elemDebug.setAttribute( "bounding-boxes", mShowTerrainBoundingBoxes ? 1 : 0 );
191  elemDebug.setAttribute( "terrain-tile-info", mShowTerrainTileInfo ? 1 : 0 );
192  elem.appendChild( elemDebug );
193 
194  return elem;
195 }
196 
198 {
199  for ( int i = 0; i < mLayers.count(); ++i )
200  {
201  QgsMapLayerRef &layerRef = mLayers[i];
202  layerRef.setLayer( project.mapLayer( layerRef.layerId ) );
203  }
204 
205  mTerrainGenerator->resolveReferences( project );
206 
207  for ( int i = 0; i < mRenderers.count(); ++i )
208  {
209  QgsAbstract3DRenderer *renderer = mRenderers[i];
210  renderer->resolveReferences( project );
211  }
212 }
213 
215 {
216  return Qgs3DUtils::mapToWorldCoordinates( mapCoords, mOrigin );
217 }
218 
220 {
221  return Qgs3DUtils::worldToMapCoordinates( worldCoords, mOrigin );
222 }
223 
225 {
226  mCrs = crs;
227 }
228 
230 {
231  return mTransformContext;
232 }
233 
235 {
236  mTransformContext = context;
237 }
238 
239 void Qgs3DMapSettings::setBackgroundColor( const QColor &color )
240 {
241  if ( color == mBackgroundColor )
242  return;
243 
244  mBackgroundColor = color;
245  emit backgroundColorChanged();
246 }
247 
249 {
250  return mBackgroundColor;
251 }
252 
253 void Qgs3DMapSettings::setSelectionColor( const QColor &color )
254 {
255  if ( color == mSelectionColor )
256  return;
257 
258  mSelectionColor = color;
259  emit selectionColorChanged();
260 }
261 
263 {
264  return mSelectionColor;
265 }
266 
268 {
269  if ( zScale == mTerrainVerticalScale )
270  return;
271 
272  mTerrainVerticalScale = zScale;
274 }
275 
277 {
278  return mTerrainVerticalScale;
279 }
280 
281 void Qgs3DMapSettings::setLayers( const QList<QgsMapLayer *> &layers )
282 {
283  QList<QgsMapLayerRef> lst;
284  lst.reserve( layers.count() );
285  Q_FOREACH ( QgsMapLayer *layer, layers )
286  {
287  lst.append( layer );
288  }
289 
290  if ( mLayers == lst )
291  return;
292 
293  mLayers = lst;
294  emit layersChanged();
295 }
296 
297 QList<QgsMapLayer *> Qgs3DMapSettings::layers() const
298 {
299  QList<QgsMapLayer *> lst;
300  lst.reserve( mLayers.count() );
301  Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers )
302  {
303  if ( layerRef.layer )
304  lst.append( layerRef.layer );
305  }
306  return lst;
307 }
308 
310 {
311  if ( mMapTileResolution == res )
312  return;
313 
314  mMapTileResolution = res;
316 }
317 
319 {
320  return mMapTileResolution;
321 }
322 
324 {
325  if ( mMaxTerrainScreenError == error )
326  return;
327 
328  mMaxTerrainScreenError = error;
330 }
331 
333 {
334  return mMaxTerrainScreenError;
335 }
336 
338 {
339  if ( mMaxTerrainGroundError == error )
340  return;
341 
342  mMaxTerrainGroundError = error;
344 }
345 
347 {
348  return mMaxTerrainGroundError;
349 }
350 
352 {
353  mTerrainGenerator.reset( gen );
355 }
356 
357 void Qgs3DMapSettings::setRenderers( const QList<QgsAbstract3DRenderer *> &renderers )
358 {
359  mRenderers = renderers;
360 }
361 
363 {
364  if ( mShowTerrainBoundingBoxes == enabled )
365  return;
366 
367  mShowTerrainBoundingBoxes = enabled;
369 }
370 
372 {
373  if ( mShowTerrainTileInfo == enabled )
374  return;
375 
376  mShowTerrainTileInfo = enabled;
378 }
379 
381 {
382  if ( mShowLabels == enabled )
383  return;
384 
385  mShowLabels = enabled;
386  emit showLabelsChanged();
387 }
float maxTerrainScreenError() const
Returns maximum allowed screen error of terrain tiles in pixels.
QList< QgsMapLayer * > layers() const
Returns the list of map layers to be rendered as a texture of the terrain.
The class is used as a container of context for various read/write operations on other objects...
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a DOM element, to be used later with readXml()
3 Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double preci...
Definition: qgsvector3d.h:29
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets coordinate reference system used in the 3D scene.
3 Terrain generator that creates a simple square flat area.
Base class for all map layer types.
Definition: qgsmaplayer.h:61
void maxTerrainGroundErrorChanged()
Emitted when the maximum terrain ground error has changed.
virtual void resolveReferences(const QgsProject &project)
Resolves references to other objects - second phase of loading - after readXml()
void setTerrainGenerator(QgsTerrainGenerator *gen)
Sets terrain generator.
QColor selectionColor() const
Returns color used for selected features.
_LayerRef< QgsMapLayer > QgsMapLayerRef
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used in the 3D scene.
Base class for all renderers that may to participate in 3D view.
void layersChanged()
Emitted when the list of map layers for terrain texture has changed.
void setShowTerrainTilesInfo(bool enabled)
Sets whether to display extra tile info on top of terrain tiles (for debugging)
QgsVector3D worldToMapCoordinates(const QgsVector3D &worldCoords) const
Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x...
void terrainVerticalScaleChanged()
Emitted when the vertical scale of the terrain has changed.
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:45
3 Definition of the world
3 Terrain generator using downloaded terrain tiles using quantized mesh specification ...
float maxTerrainGroundError() const
Returns maximum ground error of terrain tiles in world units.
virtual void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const =0
Writes renderer&#39;s properties to given XML element.
double z() const
Returns Z coordinate.
Definition: qgsvector3d.h:47
static QgsVector3D worldToMapCoordinates(const QgsVector3D &worldCoords, const QgsVector3D &origin)
Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x...
Definition: qgs3dutils.cpp:290
QString layerId
Original layer ID.
void setRenderers(const QList< QgsAbstract3DRenderer *> &renderers)
Sets list of extra 3D renderers to use in the scene. Takes ownership of the objects.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
virtual QString type() const =0
Returns unique identifier of the renderer class (used to identify subclass)
void setCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets CRS of the terrain.
QPointer< TYPE > layer
Weak pointer to map layer.
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context, which stores various information regarding which datum transfo...
int mapTileResolution() const
Returns resolution (in pixels) of the texture of a terrain tile.
void selectionColorChanged()
Emitted when the selection color has changed.
static QgsVector3D mapToWorldCoordinates(const QgsVector3D &mapCoords, const QgsVector3D &origin)
Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x...
Definition: qgs3dutils.cpp:282
void terrainGeneratorChanged()
Emitted when the terrain generator has changed.
Reads and writes project states.
Definition: qgsproject.h:85
QColor backgroundColor() const
Returns background color of the 3D map view.
void showTerrainBoundingBoxesChanged()
Emitted when the flag whether terrain&#39;s bounding boxes are shown has changed.
Contains information about the context in which a coordinate transform is executed.
static QString typeToString(Type type)
Converts terrain generator type enumeration into a string.
void setLayer(TYPE *l)
Sets the reference to point to a specified layer.
void setMaxTerrainGroundError(float error)
Returns maximum ground error of terrain tiles in world units.
void mapTileResolutionChanged()
Emitted when the map tile resoulution has changed.
void setTerrainVerticalScale(double zScale)
Sets vertical scale (exaggeration) of terrain (1 = true scale, > 1 = hills get more pronounced) ...
QgsVector3D mapToWorldCoordinates(const QgsVector3D &mapCoords) const
Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x...
3D renderer that renders all features of a vector layer with the same 3D symbol.
void showTerrainTilesInfoChanged()
Emitted when the flag whether terrain&#39;s tile info is shown has changed.
double terrainVerticalScale() const
Returns vertical scale (exaggeration) of terrain.
void setMapTileResolution(int res)
Sets resolution (in pixels) of the texture of a terrain tile.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads renderer&#39;s properties from given XML element.
Qgs3DMapSettings()=default
Constructor for Qgs3DMapSettings.
void showLabelsChanged()
Emitted when the flag whether labels are displayed on terrain tiles has changed.
void maxTerrainScreenErrorChanged()
Emitted when the maximum terrain screen error has changed.
3 Base class for generators of terrain.
QList< QgsAbstract3DRenderer * > renderers() const
Returns list of extra 3D renderers.
void setBackgroundColor(const QColor &color)
Sets background color of the 3D map view.
3 Implementation of terrain generator that uses a raster layer with DEM to build terrain.
This class represents a coordinate reference system (CRS).
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets CRS of the terrain.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
~Qgs3DMapSettings() override
void setShowLabels(bool enabled)
Sets whether to display labels on terrain tiles.
virtual QgsAbstract3DRenderer * clone() const =0
Returns a cloned instance.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from a DOM element previously written by writeXml()
void backgroundColorChanged()
Emitted when the background color has changed.
void setLayers(const QList< QgsMapLayer *> &layers)
Sets the list of map layers to be rendered as a texture of the terrain.
void setMaxTerrainScreenError(float error)
Sets maximum allowed screen error of terrain tiles in pixels.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
void resolveReferences(const QgsProject &project)
Resolves references to other objects (map layers) after the call to readXml()
void setShowTerrainBoundingBoxes(bool enabled)
Sets whether to display bounding boxes of terrain tiles (for debugging)
void setSelectionColor(const QColor &color)
Sets color used for selected features.
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:43
QgsTerrainGenerator * terrainGenerator() const
Returns terrain generator. It takes care of producing terrain tiles from the input data...