QGIS API Documentation  3.24.2-Tisler (13c1a02865)
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 
18 #include "qgs3dutils.h"
20 #include "qgsdemterraingenerator.h"
21 #include "qgsmeshterraingenerator.h"
24 #include "qgsmeshlayer3drenderer.h"
26 
27 #include <QDomDocument>
28 #include <QDomElement>
29 
30 #include "qgssymbollayerutils.h"
31 #include "qgsrasterlayer.h"
32 
34  : QObject( nullptr )
35 {
36  connect( this, &Qgs3DMapSettings::settingsChanged, [&]()
37  {
39  } );
40  connectChangedSignalsToSettingsChanged();
41 }
42 
44  : QObject( nullptr )
45  , QgsTemporalRangeObject( other )
46  , mOrigin( other.mOrigin )
47  , mCrs( other.mCrs )
48  , mBackgroundColor( other.mBackgroundColor )
49  , mSelectionColor( other.mSelectionColor )
50  , mTerrainVerticalScale( other.mTerrainVerticalScale )
51  , mTerrainGenerator( other.mTerrainGenerator ? other.mTerrainGenerator->clone() : nullptr )
52  , mMapTileResolution( other.mMapTileResolution )
53  , mMaxTerrainScreenError( other.mMaxTerrainScreenError )
54  , mMaxTerrainGroundError( other.mMaxTerrainGroundError )
55  , mTerrainElevationOffset( other.mTerrainElevationOffset )
56  , mTerrainShadingEnabled( other.mTerrainShadingEnabled )
57  , mTerrainShadingMaterial( other.mTerrainShadingMaterial )
58  , mTerrainMapTheme( other.mTerrainMapTheme )
59  , mShowTerrainBoundingBoxes( other.mShowTerrainBoundingBoxes )
60  , mShowTerrainTileInfo( other.mShowTerrainTileInfo )
61  , mShowCameraViewCenter( other.mShowCameraViewCenter )
62  , mShowCameraRotationCenter( other.mShowCameraRotationCenter )
63  , mShowLightSources( other.mShowLightSources )
64  , mShowLabels( other.mShowLabels )
65  , mPointLights( other.mPointLights )
66  , mDirectionalLights( other.mDirectionalLights )
67  , mFieldOfView( other.mFieldOfView )
68  , mProjectionType( other.mProjectionType )
69  , mCameraNavigationMode( other.mCameraNavigationMode )
70  , mCameraMovementSpeed( other.mCameraMovementSpeed )
71  , mLayers( other.mLayers )
72  , mRenderers() // initialized in body
73  , mTransformContext( other.mTransformContext )
74  , mPathResolver( other.mPathResolver )
75  , mMapThemes( other.mMapThemes )
76  , mDpi( other.mDpi )
77  , mIsFpsCounterEnabled( other.mIsFpsCounterEnabled )
78  , mIsSkyboxEnabled( other.mIsSkyboxEnabled )
79  , mSkyboxSettings( other.mSkyboxSettings )
80  , mShadowSettings( other.mShadowSettings )
81  , mEyeDomeLightingEnabled( other.mEyeDomeLightingEnabled )
82  , mEyeDomeLightingStrength( other.mEyeDomeLightingStrength )
83  , mEyeDomeLightingDistance( other.mEyeDomeLightingDistance )
84  , mDebugShadowMapEnabled( other.mDebugShadowMapEnabled )
85  , mDebugShadowMapCorner( other.mDebugShadowMapCorner )
86  , mDebugShadowMapSize( other.mDebugShadowMapSize )
87  , mDebugDepthMapEnabled( other.mDebugDepthMapEnabled )
88  , mDebugDepthMapCorner( other.mDebugDepthMapCorner )
89  , mDebugDepthMapSize( other.mDebugDepthMapSize )
90  , mTerrainRenderingEnabled( other.mTerrainRenderingEnabled )
91  , mRendererUsage( other.mRendererUsage )
92 {
93  for ( QgsAbstract3DRenderer *renderer : std::as_const( other.mRenderers ) )
94  {
95  mRenderers << renderer->clone();
96  }
97 
98  connect( this, &Qgs3DMapSettings::settingsChanged, [&]()
99  {
101  } );
102  connectChangedSignalsToSettingsChanged();
103 }
104 
106 {
107  qDeleteAll( mRenderers );
108 }
109 
110 void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
111 {
113  QDomElement elemOrigin = elem.firstChildElement( QStringLiteral( "origin" ) );
114  mOrigin = QgsVector3D(
115  elemOrigin.attribute( QStringLiteral( "x" ) ).toDouble(),
116  elemOrigin.attribute( QStringLiteral( "y" ) ).toDouble(),
117  elemOrigin.attribute( QStringLiteral( "z" ) ).toDouble() );
118 
119  QDomElement elemCamera = elem.firstChildElement( QStringLiteral( "camera" ) );
120  if ( !elemCamera.isNull() )
121  {
122  mFieldOfView = elemCamera.attribute( QStringLiteral( "field-of-view" ), QStringLiteral( "45" ) ).toFloat();
123  mProjectionType = static_cast< Qt3DRender::QCameraLens::ProjectionType >( elemCamera.attribute( QStringLiteral( "projection-type" ), QStringLiteral( "1" ) ).toInt() );
124  QString cameraNavigationMode = elemCamera.attribute( QStringLiteral( "camera-navigation-mode" ), QStringLiteral( "basic-navigation" ) );
125  if ( cameraNavigationMode == QLatin1String( "terrain-based-navigation" ) )
126  mCameraNavigationMode = QgsCameraController::NavigationMode::TerrainBasedNavigation;
127  else if ( cameraNavigationMode == QLatin1String( "walk-navigation" ) )
128  mCameraNavigationMode = QgsCameraController::NavigationMode::WalkNavigation;
129  mCameraMovementSpeed = elemCamera.attribute( QStringLiteral( "camera-movement-speed" ), QStringLiteral( "5.0" ) ).toDouble();
130  }
131 
132  QDomElement elemColor = elem.firstChildElement( QStringLiteral( "color" ) );
133  if ( !elemColor.isNull() )
134  {
135  mBackgroundColor = QgsSymbolLayerUtils::decodeColor( elemColor.attribute( QStringLiteral( "background" ) ) );
136  mSelectionColor = QgsSymbolLayerUtils::decodeColor( elemColor.attribute( QStringLiteral( "selection" ) ) );
137  }
138 
139  QDomElement elemCrs = elem.firstChildElement( QStringLiteral( "crs" ) );
140  mCrs.readXml( elemCrs );
141 
142  QDomElement elemTerrain = elem.firstChildElement( QStringLiteral( "terrain" ) );
143  mTerrainRenderingEnabled = elemTerrain.attribute( QStringLiteral( "terrain-rendering-enabled" ), QStringLiteral( "1" ) ).toInt();
144  mTerrainVerticalScale = elemTerrain.attribute( QStringLiteral( "exaggeration" ), QStringLiteral( "1" ) ).toFloat();
145  mMapTileResolution = elemTerrain.attribute( QStringLiteral( "texture-size" ), QStringLiteral( "512" ) ).toInt();
146  mMaxTerrainScreenError = elemTerrain.attribute( QStringLiteral( "max-terrain-error" ), QStringLiteral( "3" ) ).toFloat();
147  mMaxTerrainGroundError = elemTerrain.attribute( QStringLiteral( "max-ground-error" ), QStringLiteral( "1" ) ).toFloat();
148  mTerrainShadingEnabled = elemTerrain.attribute( QStringLiteral( "shading-enabled" ), QStringLiteral( "0" ) ).toInt();
149  mTerrainElevationOffset = elemTerrain.attribute( QStringLiteral( "elevation-offset" ), QStringLiteral( "0.0" ) ).toFloat();
150 
151  QDomElement elemTerrainShadingMaterial = elemTerrain.firstChildElement( QStringLiteral( "shading-material" ) );
152  if ( !elemTerrainShadingMaterial.isNull() )
153  mTerrainShadingMaterial.readXml( elemTerrainShadingMaterial, context );
154  mTerrainMapTheme = elemTerrain.attribute( QStringLiteral( "map-theme" ) );
155  mShowLabels = elemTerrain.attribute( QStringLiteral( "show-labels" ), QStringLiteral( "0" ) ).toInt();
156 
157  mPointLights.clear();
158  QDomElement elemPointLights = elem.firstChildElement( QStringLiteral( "point-lights" ) );
159  if ( !elemPointLights.isNull() )
160  {
161  QDomElement elemPointLight = elemPointLights.firstChildElement( QStringLiteral( "point-light" ) );
162  while ( !elemPointLight.isNull() )
163  {
164  QgsPointLightSettings pointLight;
165  pointLight.readXml( elemPointLight );
166  mPointLights << pointLight;
167  elemPointLight = elemPointLight.nextSiblingElement( QStringLiteral( "point-light" ) );
168  }
169  }
170  else
171  {
172  // QGIS <= 3.4 did not have light configuration
173  QgsPointLightSettings defaultLight;
174  defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
175  mPointLights << defaultLight;
176  }
177 
178  mDirectionalLights.clear();
179  QDomElement elemDirectionalLights = elem.firstChildElement( QStringLiteral( "directional-lights" ) );
180  if ( !elemDirectionalLights.isNull() )
181  {
182  QDomElement elemDirectionalLight = elemDirectionalLights.firstChildElement( QStringLiteral( "directional-light" ) );
183  while ( !elemDirectionalLight.isNull() )
184  {
185  QgsDirectionalLightSettings directionalLight;
186  directionalLight.readXml( elemDirectionalLight );
187  mDirectionalLights << directionalLight;
188  elemDirectionalLight = elemDirectionalLight.nextSiblingElement( QStringLiteral( "directional-light" ) );
189  }
190  }
191 
192  QDomElement elemMapLayers = elemTerrain.firstChildElement( QStringLiteral( "layers" ) );
193  QDomElement elemMapLayer = elemMapLayers.firstChildElement( QStringLiteral( "layer" ) );
194  QList<QgsMapLayerRef> mapLayers;
195  while ( !elemMapLayer.isNull() )
196  {
197  mapLayers << QgsMapLayerRef( elemMapLayer.attribute( QStringLiteral( "id" ) ) );
198  elemMapLayer = elemMapLayer.nextSiblingElement( QStringLiteral( "layer" ) );
199  }
200  mLayers = mapLayers; // needs to resolve refs afterwards
201 
202  QDomElement elemTerrainGenerator = elemTerrain.firstChildElement( QStringLiteral( "generator" ) );
203  QString terrainGenType = elemTerrainGenerator.attribute( QStringLiteral( "type" ) );
204  if ( terrainGenType == QLatin1String( "dem" ) )
205  {
206  QgsDemTerrainGenerator *demTerrainGenerator = new QgsDemTerrainGenerator;
207  demTerrainGenerator->setCrs( mCrs, mTransformContext );
208  setTerrainGenerator( demTerrainGenerator );
209  }
210  else if ( terrainGenType == QLatin1String( "online" ) )
211  {
212  QgsOnlineTerrainGenerator *onlineTerrainGenerator = new QgsOnlineTerrainGenerator;
213  onlineTerrainGenerator->setCrs( mCrs, mTransformContext );
214  setTerrainGenerator( onlineTerrainGenerator );
215  }
216  else if ( terrainGenType == QLatin1String( "mesh" ) )
217  {
218  QgsMeshTerrainGenerator *meshTerrainGenerator = new QgsMeshTerrainGenerator;
219  meshTerrainGenerator->setCrs( mCrs, mTransformContext );
220  setTerrainGenerator( meshTerrainGenerator );
221  }
222  else // "flat"
223  {
225  flatGen->setCrs( mCrs );
226  setTerrainGenerator( flatGen );
227  }
228  mTerrainGenerator->readXml( elemTerrainGenerator );
229 
230  qDeleteAll( mRenderers );
231  mRenderers.clear();
232 
233  QDomElement elemRenderers = elem.firstChildElement( QStringLiteral( "renderers" ) );
234  QDomElement elemRenderer = elemRenderers.firstChildElement( QStringLiteral( "renderer" ) );
235  while ( !elemRenderer.isNull() )
236  {
237  QgsAbstract3DRenderer *renderer = nullptr;
238  QString type = elemRenderer.attribute( QStringLiteral( "type" ) );
239  if ( type == QLatin1String( "vector" ) )
240  {
241  renderer = new QgsVectorLayer3DRenderer;
242  }
243  else if ( type == QLatin1String( "mesh" ) )
244  {
245  renderer = new QgsMeshLayer3DRenderer;
246  }
247  else if ( type == QLatin1String( "pointcloud" ) )
248  {
249  renderer = new QgsPointCloudLayer3DRenderer;
250  }
251 
252  if ( renderer )
253  {
254  renderer->readXml( elemRenderer, context );
255  mRenderers.append( renderer );
256  }
257  elemRenderer = elemRenderer.nextSiblingElement( QStringLiteral( "renderer" ) );
258  }
259 
260  QDomElement elemSkybox = elem.firstChildElement( QStringLiteral( "skybox" ) );
261  mIsSkyboxEnabled = elemSkybox.attribute( QStringLiteral( "skybox-enabled" ) ).toInt();
262  mSkyboxSettings.readXml( elemSkybox, context );
263 
264  QDomElement elemShadows = elem.firstChildElement( QStringLiteral( "shadow-rendering" ) );
265  mShadowSettings.readXml( elemShadows, context );
266 
267  QDomElement elemEyeDomeLighting = elem.firstChildElement( QStringLiteral( "eye-dome-lighting" ) );
268  mEyeDomeLightingEnabled = elemEyeDomeLighting.attribute( "enabled", QStringLiteral( "0" ) ).toInt();
269  mEyeDomeLightingStrength = elemEyeDomeLighting.attribute( "eye-dome-lighting-strength", QStringLiteral( "1000.0" ) ).toDouble();
270  mEyeDomeLightingDistance = elemEyeDomeLighting.attribute( "eye-dome-lighting-distance", QStringLiteral( "1" ) ).toInt();
271 
272  QDomElement elemDebugSettings = elem.firstChildElement( QStringLiteral( "debug-settings" ) );
273  mDebugShadowMapEnabled = elemDebugSettings.attribute( QStringLiteral( "shadowmap-enabled" ), QStringLiteral( "0" ) ).toInt();
274  mDebugShadowMapCorner = static_cast<Qt::Corner>( elemDebugSettings.attribute( QStringLiteral( "shadowmap-corner" ), "0" ).toInt() );
275  mDebugShadowMapSize = elemDebugSettings.attribute( QStringLiteral( "shadowmap-size" ), QStringLiteral( "0.2" ) ).toDouble();
276 
277  mDebugDepthMapEnabled = elemDebugSettings.attribute( QStringLiteral( "depthmap-enabled" ), QStringLiteral( "0" ) ).toInt();
278  mDebugDepthMapCorner = static_cast<Qt::Corner>( elemDebugSettings.attribute( QStringLiteral( "depthmap-corner" ), QStringLiteral( "1" ) ).toInt() );
279  mDebugDepthMapSize = elemDebugSettings.attribute( QStringLiteral( "depthmap-size" ), QStringLiteral( "0.2" ) ).toDouble();
280 
281  QDomElement elemDebug = elem.firstChildElement( QStringLiteral( "debug" ) );
282  mShowTerrainBoundingBoxes = elemDebug.attribute( QStringLiteral( "bounding-boxes" ), QStringLiteral( "0" ) ).toInt();
283  mShowTerrainTileInfo = elemDebug.attribute( QStringLiteral( "terrain-tile-info" ), QStringLiteral( "0" ) ).toInt();
284  mShowCameraViewCenter = elemDebug.attribute( QStringLiteral( "camera-view-center" ), QStringLiteral( "0" ) ).toInt();
285  mShowCameraRotationCenter = elemDebug.attribute( QStringLiteral( "camera-rotation-center" ), QStringLiteral( "0" ) ).toInt();
286  mShowLightSources = elemDebug.attribute( QStringLiteral( "show-light-sources" ), QStringLiteral( "0" ) ).toInt();
287  mIsFpsCounterEnabled = elemDebug.attribute( QStringLiteral( "show-fps-counter" ), QStringLiteral( "0" ) ).toInt();
288 
289  QDomElement elemTemporalRange = elem.firstChildElement( QStringLiteral( "temporal-range" ) );
290  QDateTime start = QDateTime::fromString( elemTemporalRange.attribute( QStringLiteral( "start" ) ), Qt::ISODate );
291  QDateTime end = QDateTime::fromString( elemTemporalRange.attribute( QStringLiteral( "end" ) ), Qt::ISODate );
292  setTemporalRange( QgsDateTimeRange( start, end ) );
293 }
294 
295 QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
296 {
297  QDomElement elem = doc.createElement( QStringLiteral( "qgis3d" ) );
298 
299  QDomElement elemOrigin = doc.createElement( QStringLiteral( "origin" ) );
300  elemOrigin.setAttribute( QStringLiteral( "x" ), QString::number( mOrigin.x() ) );
301  elemOrigin.setAttribute( QStringLiteral( "y" ), QString::number( mOrigin.y() ) );
302  elemOrigin.setAttribute( QStringLiteral( "z" ), QString::number( mOrigin.z() ) );
303  elem.appendChild( elemOrigin );
304 
305  QDomElement elemCamera = doc.createElement( QStringLiteral( "camera" ) );
306  elemCamera.setAttribute( QStringLiteral( "field-of-view" ), mFieldOfView );
307  elemCamera.setAttribute( QStringLiteral( "projection-type" ), static_cast< int >( mProjectionType ) );
308  switch ( mCameraNavigationMode )
309  {
311  elemCamera.setAttribute( QStringLiteral( "camera-navigation-mode" ), QStringLiteral( "terrain-based-navigation" ) );
312  break;
314  elemCamera.setAttribute( QStringLiteral( "camera-navigation-mode" ), QStringLiteral( "walk-navigation" ) );
315  break;
316  }
317  elemCamera.setAttribute( QStringLiteral( "camera-movement-speed" ), mCameraMovementSpeed );
318  elem.appendChild( elemCamera );
319 
320  QDomElement elemColor = doc.createElement( QStringLiteral( "color" ) );
321  elemColor.setAttribute( QStringLiteral( "background" ), QgsSymbolLayerUtils::encodeColor( mBackgroundColor ) );
322  elemColor.setAttribute( QStringLiteral( "selection" ), QgsSymbolLayerUtils::encodeColor( mSelectionColor ) );
323  elem.appendChild( elemColor );
324 
325  QDomElement elemCrs = doc.createElement( QStringLiteral( "crs" ) );
326  mCrs.writeXml( elemCrs, doc );
327  elem.appendChild( elemCrs );
328 
329  QDomElement elemTerrain = doc.createElement( QStringLiteral( "terrain" ) );
330  elemTerrain.setAttribute( QStringLiteral( "terrain-rendering-enabled" ), mTerrainRenderingEnabled ? 1 : 0 );
331  elemTerrain.setAttribute( QStringLiteral( "exaggeration" ), QString::number( mTerrainVerticalScale ) );
332  elemTerrain.setAttribute( QStringLiteral( "texture-size" ), mMapTileResolution );
333  elemTerrain.setAttribute( QStringLiteral( "max-terrain-error" ), QString::number( mMaxTerrainScreenError ) );
334  elemTerrain.setAttribute( QStringLiteral( "max-ground-error" ), QString::number( mMaxTerrainGroundError ) );
335  elemTerrain.setAttribute( QStringLiteral( "shading-enabled" ), mTerrainShadingEnabled ? 1 : 0 );
336  elemTerrain.setAttribute( QStringLiteral( "elevation-offset" ), mTerrainElevationOffset );
337 
338  QDomElement elemTerrainShadingMaterial = doc.createElement( QStringLiteral( "shading-material" ) );
339  mTerrainShadingMaterial.writeXml( elemTerrainShadingMaterial, context );
340  elemTerrain.appendChild( elemTerrainShadingMaterial );
341  elemTerrain.setAttribute( QStringLiteral( "map-theme" ), mTerrainMapTheme );
342  elemTerrain.setAttribute( QStringLiteral( "show-labels" ), mShowLabels ? 1 : 0 );
343 
344  QDomElement elemPointLights = doc.createElement( QStringLiteral( "point-lights" ) );
345  for ( const QgsPointLightSettings &pointLight : std::as_const( mPointLights ) )
346  {
347  QDomElement elemPointLight = pointLight.writeXml( doc );
348  elemPointLights.appendChild( elemPointLight );
349  }
350  elem.appendChild( elemPointLights );
351 
352  QDomElement elemDirectionalLights = doc.createElement( QStringLiteral( "directional-lights" ) );
353  for ( const QgsDirectionalLightSettings &directionalLight : std::as_const( mDirectionalLights ) )
354  {
355  QDomElement elemDirectionalLight = directionalLight.writeXml( doc );
356  elemDirectionalLights.appendChild( elemDirectionalLight );
357  }
358  elem.appendChild( elemDirectionalLights );
359 
360  QDomElement elemMapLayers = doc.createElement( QStringLiteral( "layers" ) );
361  for ( const QgsMapLayerRef &layerRef : mLayers )
362  {
363  QDomElement elemMapLayer = doc.createElement( QStringLiteral( "layer" ) );
364  elemMapLayer.setAttribute( QStringLiteral( "id" ), layerRef.layerId );
365  elemMapLayers.appendChild( elemMapLayer );
366  }
367  elemTerrain.appendChild( elemMapLayers );
368 
369  QDomElement elemTerrainGenerator = doc.createElement( QStringLiteral( "generator" ) );
370  elemTerrainGenerator.setAttribute( QStringLiteral( "type" ), QgsTerrainGenerator::typeToString( mTerrainGenerator->type() ) );
371  mTerrainGenerator->writeXml( elemTerrainGenerator );
372  elemTerrain.appendChild( elemTerrainGenerator );
373  elem.appendChild( elemTerrain );
374 
375  QDomElement elemRenderers = doc.createElement( QStringLiteral( "renderers" ) );
376  for ( const QgsAbstract3DRenderer *renderer : mRenderers )
377  {
378  QDomElement elemRenderer = doc.createElement( QStringLiteral( "renderer" ) );
379  elemRenderer.setAttribute( QStringLiteral( "type" ), renderer->type() );
380  renderer->writeXml( elemRenderer, context );
381  elemRenderers.appendChild( elemRenderer );
382  }
383  elem.appendChild( elemRenderers );
384 
385  QDomElement elemSkybox = doc.createElement( QStringLiteral( "skybox" ) );
386  elemSkybox.setAttribute( QStringLiteral( "skybox-enabled" ), mIsSkyboxEnabled );
387  mSkyboxSettings.writeXml( elemSkybox, context );
388  elem.appendChild( elemSkybox );
389 
390  QDomElement elemShadows = doc.createElement( QStringLiteral( "shadow-rendering" ) );
391  mShadowSettings.writeXml( elemShadows, context );
392  elem.appendChild( elemShadows );
393 
394  QDomElement elemDebug = doc.createElement( QStringLiteral( "debug" ) );
395  elemDebug.setAttribute( QStringLiteral( "bounding-boxes" ), mShowTerrainBoundingBoxes ? 1 : 0 );
396  elemDebug.setAttribute( QStringLiteral( "terrain-tile-info" ), mShowTerrainTileInfo ? 1 : 0 );
397  elemDebug.setAttribute( QStringLiteral( "camera-view-center" ), mShowCameraViewCenter ? 1 : 0 );
398  elemDebug.setAttribute( QStringLiteral( "camera-rotation-center" ), mShowCameraRotationCenter ? 1 : 0 );
399  elemDebug.setAttribute( QStringLiteral( "show-light-sources" ), mShowLightSources ? 1 : 0 );
400  elemDebug.setAttribute( QStringLiteral( "show-fps-counter" ), mIsFpsCounterEnabled ? 1 : 0 );
401  elem.appendChild( elemDebug );
402 
403  QDomElement elemEyeDomeLighting = doc.createElement( QStringLiteral( "eye-dome-lighting" ) );
404  elemEyeDomeLighting.setAttribute( "enabled", mEyeDomeLightingEnabled ? 1 : 0 );
405  elemEyeDomeLighting.setAttribute( "eye-dome-lighting-strength", mEyeDomeLightingStrength );
406  elemEyeDomeLighting.setAttribute( "eye-dome-lighting-distance", mEyeDomeLightingDistance );
407  elem.appendChild( elemEyeDomeLighting );
408 
409 
410  QDomElement elemDebugSettings = doc.createElement( QStringLiteral( "debug-settings" ) );
411  elemDebugSettings.setAttribute( QStringLiteral( "shadowmap-enabled" ), mDebugShadowMapEnabled );
412  elemDebugSettings.setAttribute( QStringLiteral( "shadowmap-corner" ), mDebugShadowMapCorner );
413  elemDebugSettings.setAttribute( QStringLiteral( "shadowmap-size" ), mDebugShadowMapSize );
414  elemDebugSettings.setAttribute( QStringLiteral( "depthmap-enabled" ), mDebugDepthMapEnabled );
415  elemDebugSettings.setAttribute( QStringLiteral( "depthmap-corner" ), mDebugDepthMapCorner );
416  elemDebugSettings.setAttribute( QStringLiteral( "depthmap-size" ), mDebugDepthMapSize );
417  elem.appendChild( elemDebugSettings );
418 
419  QDomElement elemTemporalRange = doc.createElement( QStringLiteral( "temporal-range" ) );
420  elemTemporalRange.setAttribute( QStringLiteral( "start" ), temporalRange().begin().toString( Qt::ISODate ) );
421  elemTemporalRange.setAttribute( QStringLiteral( "end" ), temporalRange().end().toString( Qt::ISODate ) );
422 
423  return elem;
424 }
425 
427 {
428  for ( int i = 0; i < mLayers.count(); ++i )
429  {
430  QgsMapLayerRef &layerRef = mLayers[i];
431  layerRef.setLayer( project.mapLayer( layerRef.layerId ) );
432  }
433 
434  mTerrainGenerator->resolveReferences( project );
435 
436  for ( int i = 0; i < mRenderers.count(); ++i )
437  {
438  QgsAbstract3DRenderer *renderer = mRenderers[i];
439  renderer->resolveReferences( project );
440  }
441 }
442 
444 {
445  return Qgs3DUtils::mapToWorldCoordinates( mapCoords, mOrigin );
446 }
447 
449 {
450  return Qgs3DUtils::worldToMapCoordinates( worldCoords, mOrigin );
451 }
452 
454 {
455  mCrs = crs;
456 }
457 
459 {
460  return mTransformContext;
461 }
462 
464 {
465  mTransformContext = context;
466 }
467 
468 void Qgs3DMapSettings::setBackgroundColor( const QColor &color )
469 {
470  if ( color == mBackgroundColor )
471  return;
472 
473  mBackgroundColor = color;
474  emit backgroundColorChanged();
475 }
476 
478 {
479  return mBackgroundColor;
480 }
481 
482 void Qgs3DMapSettings::setSelectionColor( const QColor &color )
483 {
484  if ( color == mSelectionColor )
485  return;
486 
487  mSelectionColor = color;
488  emit selectionColorChanged();
489 }
490 
492 {
493  return mSelectionColor;
494 }
495 
497 {
498  if ( zScale == mTerrainVerticalScale )
499  return;
500 
501  mTerrainVerticalScale = zScale;
503 }
504 
506 {
507  return mTerrainVerticalScale;
508 }
509 
510 void Qgs3DMapSettings::setLayers( const QList<QgsMapLayer *> &layers )
511 {
512  QList<QgsMapLayerRef> lst;
513  lst.reserve( layers.count() );
514  for ( QgsMapLayer *layer : layers )
515  {
516  lst.append( layer );
517  }
518 
519  if ( mLayers == lst )
520  return;
521 
522  mLayers = lst;
523  emit layersChanged();
524 }
525 
526 QList<QgsMapLayer *> Qgs3DMapSettings::layers() const
527 {
528  QList<QgsMapLayer *> lst;
529  lst.reserve( mLayers.count() );
530  for ( const QgsMapLayerRef &layerRef : mLayers )
531  {
532  if ( layerRef.layer )
533  lst.append( layerRef.layer );
534  }
535  return lst;
536 }
537 
539 {
540  if ( mMapTileResolution == res )
541  return;
542 
543  mMapTileResolution = res;
545 }
546 
548 {
549  return mMapTileResolution;
550 }
551 
553 {
554  if ( mMaxTerrainScreenError == error )
555  return;
556 
557  mMaxTerrainScreenError = error;
559 }
560 
562 {
563  return mMaxTerrainScreenError;
564 }
565 
567 {
568  if ( mMaxTerrainGroundError == error )
569  return;
570 
571  mMaxTerrainGroundError = error;
573 }
574 
576 {
577  if ( mTerrainElevationOffset == offset )
578  return;
579  mTerrainElevationOffset = offset;
580  emit terrainElevationOffsetChanged( mTerrainElevationOffset );
581 }
582 
584 {
585  return mMaxTerrainGroundError;
586 }
587 
589 {
590  if ( mTerrainGenerator )
591  {
592  disconnect( mTerrainGenerator.get(), &QgsTerrainGenerator::extentChanged, this, &Qgs3DMapSettings::terrainGeneratorChanged );
593  disconnect( mTerrainGenerator.get(), &QgsTerrainGenerator::terrainChanged, this, &Qgs3DMapSettings::terrainGeneratorChanged );
594  }
595 
596  mTerrainGenerator.reset( gen );
597  connect( mTerrainGenerator.get(), &QgsTerrainGenerator::extentChanged, this, &Qgs3DMapSettings::terrainGeneratorChanged );
598  connect( mTerrainGenerator.get(), &QgsTerrainGenerator::terrainChanged, this, &Qgs3DMapSettings::terrainGeneratorChanged );
599 
601 }
602 
604 {
605  if ( mTerrainShadingEnabled == enabled )
606  return;
607 
608  mTerrainShadingEnabled = enabled;
609  emit terrainShadingChanged();
610 }
611 
613 {
614  if ( mTerrainShadingMaterial == material )
615  return;
616 
617  mTerrainShadingMaterial = material;
618  emit terrainShadingChanged();
619 }
620 
621 void Qgs3DMapSettings::setTerrainMapTheme( const QString &theme )
622 {
623  if ( mTerrainMapTheme == theme )
624  return;
625 
626  mTerrainMapTheme = theme;
627  emit terrainMapThemeChanged();
628 }
629 
630 void Qgs3DMapSettings::setRenderers( const QList<QgsAbstract3DRenderer *> &renderers )
631 {
632  qDeleteAll( mRenderers );
633 
634  mRenderers = renderers;
635 
636  emit renderersChanged();
637 }
638 
640 {
641  if ( mShowTerrainBoundingBoxes == enabled )
642  return;
643 
644  mShowTerrainBoundingBoxes = enabled;
646 }
647 
649 {
650  if ( mShowTerrainTileInfo == enabled )
651  return;
652 
653  mShowTerrainTileInfo = enabled;
655 }
656 
658 {
659  if ( mShowCameraViewCenter == enabled )
660  return;
661 
662  mShowCameraViewCenter = enabled;
664 }
665 
667 {
668  if ( mShowCameraRotationCenter == enabled )
669  return;
670 
671  mShowCameraRotationCenter = enabled;
673 }
674 
675 
677 {
678  if ( mShowLightSources == enabled )
679  return;
680 
681  mShowLightSources = enabled;
683 }
684 
686 {
687  if ( mShowLabels == enabled )
688  return;
689 
690  mShowLabels = enabled;
691  emit showLabelsChanged();
692 }
693 
695 {
696  if ( mEyeDomeLightingEnabled == enabled )
697  return;
698  mEyeDomeLightingEnabled = enabled;
700 }
701 
703 {
704  if ( mEyeDomeLightingStrength == strength )
705  return;
706  mEyeDomeLightingStrength = strength;
708 }
709 
711 {
712  if ( mEyeDomeLightingDistance == distance )
713  return;
714  mEyeDomeLightingDistance = distance;
716 }
717 
718 void Qgs3DMapSettings::setPointLights( const QList<QgsPointLightSettings> &pointLights )
719 {
720  if ( mPointLights == pointLights )
721  return;
722 
723  mPointLights = pointLights;
724  emit pointLightsChanged();
725 }
726 
727 void Qgs3DMapSettings::setDirectionalLights( const QList<QgsDirectionalLightSettings> &directionalLights )
728 {
729  if ( mDirectionalLights == directionalLights )
730  return;
731 
732  mDirectionalLights = directionalLights;
734 }
735 
736 void Qgs3DMapSettings::setFieldOfView( const float fieldOfView )
737 {
738  if ( mFieldOfView == fieldOfView )
739  return;
740 
741  mFieldOfView = fieldOfView;
742  emit fieldOfViewChanged();
743 }
744 
745 void Qgs3DMapSettings::setProjectionType( const Qt3DRender::QCameraLens::ProjectionType projectionType )
746 {
747  if ( mProjectionType == projectionType )
748  return;
749 
750  mProjectionType = projectionType;
751  emit projectionTypeChanged();
752 }
753 
755 {
756  if ( mCameraNavigationMode == navigationMode )
757  return;
758 
759  mCameraNavigationMode = navigationMode;
761 }
762 
763 void Qgs3DMapSettings::setCameraMovementSpeed( double movementSpeed )
764 {
765  if ( mCameraMovementSpeed == movementSpeed )
766  return;
767 
768  mCameraMovementSpeed = movementSpeed;
770 }
771 
773 {
774  mSkyboxSettings = skyboxSettings;
775  emit skyboxSettingsChanged();
776 }
777 
779 {
780  mShadowSettings = shadowSettings;
781  emit shadowSettingsChanged();
782 }
783 
784 void Qgs3DMapSettings::setDebugShadowMapSettings( bool enabled, Qt::Corner corner, double size )
785 {
786  mDebugShadowMapEnabled = enabled;
787  mDebugShadowMapCorner = corner;
788  mDebugShadowMapSize = size;
790 }
791 
792 void Qgs3DMapSettings::setDebugDepthMapSettings( bool enabled, Qt::Corner corner, double size )
793 {
794  mDebugDepthMapEnabled = enabled;
795  mDebugDepthMapCorner = corner;
796  mDebugDepthMapSize = size;
798 }
799 
800 void Qgs3DMapSettings::setIsFpsCounterEnabled( bool fpsCounterEnabled )
801 {
802  if ( fpsCounterEnabled == mIsFpsCounterEnabled )
803  return;
804  mIsFpsCounterEnabled = fpsCounterEnabled;
805  emit fpsCounterEnabledChanged( mIsFpsCounterEnabled );
806 }
807 
808 void Qgs3DMapSettings::setTerrainRenderingEnabled( bool terrainRenderingEnabled )
809 {
810  if ( terrainRenderingEnabled == mTerrainRenderingEnabled )
811  return;
812  mTerrainRenderingEnabled = terrainRenderingEnabled;
814 }
815 
817 {
818  return mRendererUsage;
819 }
820 
822 {
823  mRendererUsage = rendererUsage;
824 }
825 
826 void Qgs3DMapSettings::connectChangedSignalsToSettingsChanged()
827 {
858 }
RendererUsage
Usage of the renderer.
Definition: qgis.h:1291
void setEyeDomeLightingStrength(double strength)
Sets the eye dome lighting strength value.
void mapTileResolutionChanged()
Emitted when the map tile resoulution has changed.
void terrainVerticalScaleChanged()
Emitted when the vertical scale of the terrain has changed.
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context, which stores various information regarding which datum transfo...
void settingsChanged()
Emitted when one of the configuration settings has changed.
void renderersChanged()
Emitted when the list of map's extra renderers have been modified.
QList< QgsAbstract3DRenderer * > renderers() const
Returns list of extra 3D renderers.
void eyeDomeLightingDistanceChanged()
Emitted when the eye dome lighting distance has changed.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from a DOM element previously written by writeXml()
void terrainShadingChanged()
Emitted when terrain shading enabled flag or terrain shading material has changed.
void setShowTerrainTilesInfo(bool enabled)
Sets whether to display extra tile info on top of terrain tiles (for debugging)
QgsVector3D mapToWorldCoordinates(const QgsVector3D &mapCoords) const
Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x,...
void setRenderers(const QList< QgsAbstract3DRenderer * > &renderers)
Sets list of extra 3D renderers to use in the scene. Takes ownership of the objects.
Qt3DRender::QCameraLens::ProjectionType projectionType() const
Returns the camera lens' projection type.
void setEyeDomeLightingEnabled(bool enabled)
Sets whether eye dome lighting will be used.
void setFieldOfView(const float fieldOfView)
Sets the camera lens' field of view.
void debugDepthMapSettingsChanged()
Emitted when depth map debugging has changed.
QList< QgsDirectionalLightSettings > directionalLights() const
Returns list of directional lights defined in the scene.
void setPointLights(const QList< QgsPointLightSettings > &pointLights)
Sets list of point lights defined in the scene.
void backgroundColorChanged()
Emitted when the background color has changed.
void showTerrainBoundingBoxesChanged()
Emitted when the flag whether terrain's bounding boxes are shown has changed.
void setDirectionalLights(const QList< QgsDirectionalLightSettings > &directionalLights)
Sets list of directional lights defined in the scene.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a DOM element, to be used later with readXml()
void setDebugDepthMapSettings(bool enabled, Qt::Corner corner, double size)
Sets the debugging settings of the depth map.
void showCameraRotationCenterChanged()
Emitted when the flag whether camera's rotation center is shown has changed.
QColor selectionColor() const
Returns color used for selected features.
void directionalLightsChanged()
Emitted when the list of directional lights changes.
void setTerrainShadingMaterial(const QgsPhongMaterialSettings &material)
Sets terrain shading material.
void cameraNavigationModeChanged()
Emitted when the camera navigation mode was changed.
void shadowSettingsChanged()
Emitted when shadow rendering settings are changed.
void setShowCameraRotationCenter(bool enabled)
Sets whether to show camera's rotation center as a sphere (for debugging)
float maxTerrainGroundError() const
Returns maximum ground error of terrain tiles in world units.
void eyeDomeLightingEnabledChanged()
Emitted when the flag whether eye dome lighting is used has changed.
void setTerrainVerticalScale(double zScale)
Sets vertical scale (exaggeration) of terrain (1 = true scale, > 1 = hills get more pronounced)
void setShowLabels(bool enabled)
Sets whether to display labels on terrain tiles.
double terrainVerticalScale() const
Returns vertical scale (exaggeration) of terrain.
void setMaxTerrainGroundError(float error)
Returns maximum ground error of terrain tiles in world units.
void setSkyboxSettings(const QgsSkyboxSettings &skyboxSettings)
Sets the current configuration of the skybox.
void skyboxSettingsChanged()
Emitted when skybox settings are changed.
void setMapTileResolution(int res)
Sets resolution (in pixels) of the texture of a terrain tile.
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of 3D map layers to be rendered in the scene.
QgsShadowSettings shadowSettings() const
Returns the current configuration of shadows.
void terrainMapThemeChanged()
Emitted when terrain's map theme has changed.
void setShadowSettings(const QgsShadowSettings &shadowSettings)
Sets the current configuration of shadow rendering.
void pointLightsChanged()
Emitted when the list of point lights changes.
void setTerrainElevationOffset(float offset)
Sets the terrain elevation offset (used to move the terrain up or down)
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets coordinate reference system used in the 3D scene.
void setEyeDomeLightingDistance(int distance)
Sets the eye dome lighting distance value (contributes to the contrast of the image.
void setShowLightSourceOrigins(bool enabled)
Sets whether to show light source origins as a sphere (for debugging)
void projectionTypeChanged()
Emitted when the camera lens projection type changes.
float fieldOfView() const
Returns the camera lens' field of view.
void selectionColorChanged()
Emitted when the selection color has changed.
void setTerrainShadingEnabled(bool enabled)
Sets whether terrain shading is enabled.
void setDebugShadowMapSettings(bool enabled, Qt::Corner corner, double size)
Sets the debugging settings of the shadow map.
void setSelectionColor(const QColor &color)
Sets color used for selected features.
void showLightSourceOriginsChanged()
Emitted when the flag whether light source origins are shown has changed.
QColor backgroundColor() const
Returns background color of the 3D map view.
void resolveReferences(const QgsProject &project)
Resolves references to other objects (map layers) after the call to readXml()
QgsVector3D worldToMapCoordinates(const QgsVector3D &worldCoords) const
Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x,...
~Qgs3DMapSettings() override
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.
void setShowCameraViewCenter(bool enabled)
Sets whether to show camera's view center as a sphere (for debugging)
int mapTileResolution() const
Returns resolution (in pixels) of the texture of a terrain tile.
bool terrainRenderingEnabled()
Returns whether the 2D terrain surface will be rendered.
void setCameraMovementSpeed(double movementSpeed)
Sets the camera movement speed.
void terrainElevationOffsetChanged(float newElevation)
Emitted when the terrain elevation offset is changed.
void setTerrainRenderingEnabled(bool terrainRenderingEnabled)
Sets whether the 2D terrain surface will be rendered in.
Qgs3DMapSettings()
Constructor for Qgs3DMapSettings.
void setBackgroundColor(const QColor &color)
Sets background color of the 3D map view.
void fpsCounterEnabledChanged(bool fpsCounterEnabled)
Emitted when the FPS counter is enabled or disabled.
void setProjectionType(const Qt3DRender::QCameraLens::ProjectionType projectionType)
Sets the camera lens' projection type.
void setCameraNavigationMode(QgsCameraController::NavigationMode navigationMode)
Sets the navigation mode for the camera.
void layersChanged()
Emitted when the list of map layers for 3d rendering has changed.
void showTerrainTilesInfoChanged()
Emitted when the flag whether terrain's tile info is shown has changed.
void eyeDomeLightingStrengthChanged()
Emitted when the eye dome lighting strength has changed.
QgsSkyboxSettings skyboxSettings() const
Returns the current configuration of the skybox.
void setMaxTerrainScreenError(float error)
Sets maximum allowed screen error of terrain tiles in pixels.
void cameraMovementSpeedChanged()
Emitted when the camera movement speed was changed.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used in the 3D scene.
void setRendererUsage(Qgis::RendererUsage rendererUsage)
Sets the renderer usage.
float maxTerrainScreenError() const
Returns maximum allowed screen error of terrain tiles in pixels.
void setShowTerrainBoundingBoxes(bool enabled)
Sets whether to display bounding boxes of terrain tiles (for debugging)
void fieldOfViewChanged()
Emitted when the camera lens field of view changes.
Qgis::RendererUsage rendererUsage() const
Returns the renderer usage.
void setIsFpsCounterEnabled(bool fpsCounterEnabled)
Sets whether FPS counter label is enabled.
QList< QgsPointLightSettings > pointLights() const
Returns list of point lights defined in the scene.
QList< QgsMapLayer * > layers() const
Returns the list of 3D map layers to be rendered in the scene.
void setTerrainMapTheme(const QString &theme)
Sets name of the map theme.
QgsCameraController::NavigationMode cameraNavigationMode() const
Returns the navigation mode used by the camera.
void terrainGeneratorChanged()
Emitted when the terrain generator has changed.
void setTerrainGenerator(QgsTerrainGenerator *gen)
Sets terrain generator.
void debugShadowMapSettingsChanged()
Emitted when shadow map debugging has changed.
void showCameraViewCenterChanged()
Emitted when the flag whether camera's view center is shown has changed.
void maxTerrainGroundErrorChanged()
Emitted when the maximum terrain ground error has changed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
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:488
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:480
Base class for all renderers that may to participate in 3D view.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads renderer's properties from given XML element.
virtual void resolveReferences(const QgsProject &project)
Resolves references to other objects - second phase of loading - after readXml()
NavigationMode
The navigation mode used by the camera.
@ WalkNavigation
Uses WASD keys or arrows to navigate in walking (first person) manner.
@ TerrainBasedNavigation
The default navigation based on the terrain.
This class represents a coordinate reference system (CRS).
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Contains information about the context in which a coordinate transform is executed.
void setCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets CRS of the terrain.
void readXml(const QDomElement &elem)
Reads configuration from a DOM element previously written using writeXml()
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets CRS of the terrain.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
3D renderer that renders all mesh triangles of a mesh layer.
void setCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets CRS of the terrain.
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const override
Writes settings to a DOM element.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads settings from a DOM element.
3D renderer that renders all points from a point cloud layer
void setPosition(const QgsVector3D &pos)
Sets position of the light (in 3D world coordinates)
void readXml(const QDomElement &elem)
Reads configuration from a DOM element previously written using writeXml()
Temporarily blocks QgsProject "dirtying" for the lifetime of the object.
Definition: qgsproject.h:2184
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:101
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:470
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:521
The class is used as a container of context for various read/write operations on other objects.
class containing the configuration of shadows rendering 3
void writeXml(QDomElement &element, const QgsReadWriteContext &context) const
Writes settings to a DOM element.
void readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads settings from a DOM element.
Contains the configuration of a skybox entity.
void readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads settings from a DOM element.
void writeXml(QDomElement &element, const QgsReadWriteContext &context) const
Writes settings to a DOM element.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
Base class for objects with an associated (optional) temporal range.
const QgsDateTimeRange & temporalRange() const
Returns the datetime range for the object.
void setTemporalRange(const QgsDateTimeRange &range)
Sets the temporal range for the object.
void terrainChanged()
Emitted when the terrain changed (for example, raster DEM or mesh have data changed)
void extentChanged()
Emitted when the terrain extent has changed.
static QString typeToString(Type type)
Converts terrain generator type enumeration into a string.
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:51
double z() const
Returns Z coordinate.
Definition: qgsvector3d.h:53
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:49
3D renderer that renders all features of a vector layer with the same 3D symbol.
_LayerRef< QgsMapLayer > QgsMapLayerRef
const QgsCoordinateReferenceSystem & crs
void setLayer(TYPE *l)
Sets the reference to point to a specified layer.
QString layerId
Original layer ID.