73#include <QOpenGLContext>
74#include <QOpenGLFunctions>
79#include <Qt3DExtras/QDiffuseSpecularMaterial>
80#include <Qt3DExtras/QForwardRenderer>
81#include <Qt3DExtras/QPhongAlphaMaterial>
82#include <Qt3DExtras/QPhongMaterial>
83#include <Qt3DExtras/QSphereMesh>
84#include <Qt3DLogic/QFrameAction>
85#include <Qt3DRender/QCamera>
86#include <Qt3DRender/QCullFace>
87#include <Qt3DRender/QDepthTest>
88#include <Qt3DRender/QEffect>
89#include <Qt3DRender/QMesh>
90#include <Qt3DRender/QRenderPass>
91#include <Qt3DRender/QRenderSettings>
92#include <Qt3DRender/QRenderState>
93#include <Qt3DRender/QSceneLoader>
94#include <Qt3DRender/QTechnique>
97#include "moc_qgs3dmapscene.cpp"
99using namespace Qt::StringLiterals;
108 onBackgroundColorChanged();
113 mEngine->renderSettings()->setRenderPolicy( Qt3DRender::QRenderSettings::OnDemand );
115 QRect viewportRect( QPoint( 0, 0 ), mEngine->size() );
121 float aspectRatio = ( float ) viewportRect.width() / viewportRect.height();
122 mEngine->camera()->lens()->setPerspectiveProjection( mMap.fieldOfView(), aspectRatio, 10.f, 10000.0f );
124 mFrameAction =
new Qt3DLogic::QFrameAction();
125 connect( mFrameAction, &Qt3DLogic::QFrameAction::triggered,
this, &Qgs3DMapScene::onFrameTriggered );
126 addComponent( mFrameAction );
132 mCameraController->resetGlobe( 10'000'000 );
134 mCameraController->resetView( 1000 );
136 addCameraViewCenterEntity( mEngine->camera() );
137 addCameraRotationCenterEntity( mCameraController );
142 createTerrainDeferred();
174 const QList<QgsMapLayer *> modelVectorLayers = mModelVectorLayers;
180 if ( renderer->
type() ==
"vector"_L1 )
183 if ( pointSymbol && pointSymbol->
shapeProperty( u
"model"_s ).toString() == url )
185 removeLayerEntity( layer );
186 addLayerEntity( layer );
189 else if ( renderer->
type() ==
"rulebased"_L1 )
195 if ( pointSymbol && pointSymbol->
shapeProperty( u
"model"_s ).toString() == url )
197 removeLayerEntity( layer );
198 addLayerEntity( layer );
214 onBackgroundSettingsChanged();
219 onEyeDomeShadingSettingsChanged();
221 onDebugShadowMapSettingsChanged();
222 onDebugDepthMapSettingsChanged();
224 onAmbientOcclusionSettingsChanged();
226 onMsaaEnabledChanged();
231 mOverlayUpdateTimer =
new QTimer(
this );
232 mOverlayUpdateTimer->setSingleShot(
true );
233 mOverlayUpdateTimer->setInterval( 250 );
234 connect( mOverlayUpdateTimer, &QTimer::timeout,
this, &Qgs3DMapScene::applyPendingOverlayUpdate );
237 onShowMapOverlayChanged();
239 onCameraMovementSpeedChanged();
241 on3DAxisSettingsChanged();
248 mCameraController->resetGlobe( 10'000'000 );
254 const double side = std::max( extent.
width(), extent.
height() );
255 double d = side / 2 / std::tan(
cameraController()->camera()->fieldOfView() / 2 * M_PI / 180 );
257 mCameraController->resetView(
static_cast<float>( d ) );
268 const double xSide = std::abs( p1.
x() - p2.
x() );
269 const double ySide = std::abs( p1.
y() - p2.
y() );
270 const double side = std::max( xSide, ySide );
272 const double fov = qDegreesToRadians(
cameraController()->camera()->fieldOfView() );
273 double distance = side / 2.0f / std::tan( fov / 2.0f );
278 distance += zRange.
upper();
282 mCameraController->setViewFromTop(
283 static_cast<float>( center.
x() - origin.
x() ),
284 static_cast<float>( center.
y() - origin.
y() ),
285 static_cast<float>( distance )
292 Qt3DRender::QCamera *camera = mCameraController->camera();
293 QVector<QgsPointXY> extent;
294 QVector<int> pointsOrder = { 0, 1, 3, 2 };
295 for (
int i : pointsOrder )
297 const QPoint p( ( ( i >> 0 ) & 1 ) ? 0 : mEngine->size().width(), ( ( i >> 1 ) & 1 ) ? 0 : mEngine->size().height() );
300 if ( dir.z() == 0.0 )
301 dir.setZ( 0.000001 );
302 double t = -ray.
origin().z() / dir.z();
306 t = camera->farPlane();
311 t = std::min<float>( t, camera->farPlane() );
313 QVector3D planePoint = ray.
origin() + t * dir;
314 QgsVector3D pMap = mMap.worldToMapCoordinates( planePoint );
323 for ( Qgs3DMapSceneEntity *entity : std::as_const( mSceneEntities ) )
324 count += entity->pendingJobsCount();
330 Qt3DRender::QCamera *camera = mCameraController->camera();
331 const double fov = camera->fieldOfView();
332 const QSize size = mEngine->size();
333 const int screenSizePx = std::max( size.width(), size.height() );
337 const double frustumWidthAtDistance = 2 * distance * tan( fov / 2 );
338 const double err = frustumWidthAtDistance * epsilon / screenSizePx;
342void Qgs3DMapScene::onCameraChanged()
345 updateCameraNearFarPlanes();
347 onShadowSettingsChanged();
351 schedule2DMapOverlayUpdate();
359 constexpr float ORIGIN_SHIFT_THRESHOLD = 10'000;
360 if ( mSceneOriginShiftEnabled && mEngine->
camera()->position().length() > ORIGIN_SHIFT_THRESHOLD )
368bool Qgs3DMapScene::updateScene(
bool forceUpdate )
370 if ( !mSceneUpdatesEnabled )
376 QgsEventTracing::ScopedEvent traceEvent( u
"3D"_s, forceUpdate ? u
"Force update scene"_s : u
"Update scene"_s );
378 Qgs3DMapSceneEntity::SceneContext sceneContext;
379 Qt3DRender::QCamera *camera = mEngine->camera();
380 sceneContext.cameraFov = camera->fieldOfView();
381 sceneContext.cameraPos = camera->position();
382 const QSize size = mEngine->size();
383 sceneContext.screenSizePx = std::max( size.width(), size.height() );
391 QMatrix4x4 projMatrix;
392 switch ( mMap.projectionType() )
394 case Qt3DRender::QCameraLens::PerspectiveProjection:
396 float fovRadians = ( camera->fieldOfView() / 2.0f ) *
static_cast<float>( M_PI ) / 180.0f;
397 float fovCotan = std::cos( fovRadians ) / std::sin( fovRadians );
400 fovCotan / camera->aspectRatio(), 0, 0, 0,
408 case Qt3DRender::QCameraLens::OrthographicProjection:
410 Qt3DRender::QCameraLens *lens = camera->lens();
413 2.0f / ( lens->right() - lens->left() ), 0, 0, 0,
414 0, 2.0f / ( lens->top() - lens->bottom() ), 0, 0,
416 -( lens->left() + lens->right() ) / ( lens->right() - lens->left() ), -( lens->top() + lens->bottom() ) / ( lens->top() - lens->bottom() ), -1.0f, 1.0f
423 projMatrix = camera->projectionMatrix();
425 sceneContext.viewProjectionMatrix = projMatrix * camera->viewMatrix();
428 bool anyUpdated =
false;
429 for ( Qgs3DMapSceneEntity *entity : std::as_const( mSceneEntities ) )
431 if ( forceUpdate || ( entity->isEnabled() && entity->needsUpdate() ) )
434 entity->handleSceneUpdate( sceneContext );
435 if ( entity->hasReachedGpuMemoryLimit() )
445bool Qgs3DMapScene::updateCameraNearFarPlanes()
460 QMatrix4x4 viewMatrix = camera->viewMatrix();
466 for ( Qgs3DMapSceneEntity *se : std::as_const( mSceneEntities ) )
468 const QgsRange<float> depthRange = se->getNearFarPlaneRange( viewMatrix );
470 fnear = std::min( fnear, depthRange.
lower() );
471 ffar = std::max( ffar, depthRange.
upper() );
480 if ( fnear == 1e9 && ffar == 0 )
483 sceneZRange = sceneZRange.
isInfinite() ? QgsDoubleRange( 0.0, 0.0 ) : sceneZRange;
490 std::swap( fnear, ffar );
493 float newFar = ffar * 2;
494 float newNear = fnear / 2;
497 camera->setFarPlane( newFar );
498 camera->setNearPlane( newNear );
505void Qgs3DMapScene::onFrameTriggered(
float dt )
507 QgsEventTracing::addEvent( QgsEventTracing::EventType::Instant, u
"3D"_s, u
"Frame begins"_s );
509 mCameraController->frameTriggered( dt );
514 updateCameraNearFarPlanes();
517 static int frameCount = 0;
518 static float accumulatedTime = 0.0f;
520 if ( !mMap.isFpsCounterEnabled() )
528 accumulatedTime += dt;
529 if ( accumulatedTime >= 0.2f )
531 float fps = ( float ) frameCount / accumulatedTime;
533 accumulatedTime = 0.0f;
538void Qgs3DMapScene::update2DMapOverlay(
const QVector<QgsPointXY> &extent2DAsPoints )
540 QgsFrameGraph *frameGraph = mEngine->frameGraph();
543 if ( !mMap.is2DMapOverlayEnabled() )
545 if ( mMapOverlayEntity )
547 mMapOverlayEntity.reset();
549 overlayRenderView.
setEnabled( mMap.debugShadowMapEnabled() || mMap.debugDepthMapEnabled() );
553 if ( !mMapOverlayEntity )
555 QgsWindow3DEngine *
engine = qobject_cast<QgsWindow3DEngine *>( mEngine );
556 mMapOverlayEntity.reset(
new QgsMapOverlayEntity(
engine, &overlayRenderView, &mMap,
this ) );
557 mMapOverlayEntity->setEnabled(
true );
562 Qt3DRender::QCamera *camera = mEngine->camera();
563 const QgsVector3D extentCenter3D = mMap.worldToMapCoordinates( camera->position() );
564 const QgsPointXY extentCenter2D( extentCenter3D.
x(), extentCenter3D.
y() );
571 double minHalfExtent = std::numeric_limits<double>::max();
572 double maxHalfExtent = 0.0;
573 for (
const QgsPointXY &extentPoint : extent2DAsPoints )
575 const double distance = extentCenter2D.distance( extentPoint );
576 minHalfExtent = std::min( minHalfExtent, distance );
577 maxHalfExtent = std::max( maxHalfExtent, distance );
581 const double sceneHalfExtent = 0.6 * std::max( fullExtent.
width(), fullExtent.
height() );
583 minHalfExtent = std::min( 50., minHalfExtent );
584 maxHalfExtent = std::min( 100., maxHalfExtent );
585 const double smoothFactor = std::sin( mCameraController->pitch() / 90.0 * M_PI_2 );
588 const double adjustedHalfExtent = std::min( 3.0 * ( minHalfExtent + smoothFactor * maxHalfExtent ), sceneHalfExtent );
591 const bool showFrustum = mMap.viewFrustumVisualizationEnabled();
592 mMapOverlayEntity->update( overviewExtent, extent2DAsPoints, mCameraController->yaw(), showFrustum );
595void Qgs3DMapScene::createTerrain()
599 mSceneEntities.removeOne( mTerrain );
607 mSceneEntities.removeOne( mGlobe );
613 if ( !mTerrainUpdateScheduled )
616 QTimer::singleShot( 0,
this, &Qgs3DMapScene::createTerrainDeferred );
617 mTerrainUpdateScheduled =
true;
626void Qgs3DMapScene::createTerrainDeferred()
628 QgsChunkedEntity *terrainOrGlobe =
nullptr;
632 mGlobe =
new QgsGlobeEntity( &mMap );
633 terrainOrGlobe = mGlobe;
635 else if ( mMap.sceneMode() ==
Qgis::SceneMode::Local && mMap.terrainRenderingEnabled() && mMap.terrainGenerator() )
637 double tile0width = mMap.terrainGenerator()->rootChunkExtent().width();
638 int maxZoomLevel =
Qgs3DUtils::maxZoomLevel( tile0width, mMap.terrainSettings()->mapTileResolution(), mMap.terrainSettings()->maximumGroundError() );
639 const QgsBox3D rootBox3D = mMap.terrainGenerator()->rootChunkBox3D( mMap );
640 float rootError = mMap.terrainGenerator()->rootChunkError( mMap );
641 const QgsBox3D clippingBox3D( mMap.extent(), rootBox3D.
zMinimum(), rootBox3D.
zMaximum() );
642 mMap.terrainGenerator()->setupQuadtree( rootBox3D, rootError, maxZoomLevel, clippingBox3D );
644 mTerrain =
new QgsTerrainEntity( &mMap );
645 terrainOrGlobe = mTerrain;
648 if ( terrainOrGlobe )
651 QgsFrameGraph *frameGraph = mEngine->frameGraph();
655 terrainOrGlobe->setParent(
this );
656 terrainOrGlobe->setShowBoundingBoxes( mMap.showTerrainBoundingBoxes() );
658 mSceneEntities << terrainOrGlobe;
661 connect( terrainOrGlobe, &Qgs3DMapSceneEntity::newEntityCreated,
this, [
this]( Qt3DCore::QEntity *entity ) {
663 const QList<QgsGeoTransform *> transforms = entity->findChildren<QgsGeoTransform *>();
664 for ( QgsGeoTransform *transform : transforms )
666 transform->setOrigin( mMap.origin() );
670 handleClippingOnEntity( entity );
675 const QList<QgsMapLayer *>
layers = mMap.layers();
676 for ( QgsMapLayer *layer :
layers )
679 removeLayerEntity( layer );
682 addLayerEntity( layer );
687 mTerrainUpdateScheduled =
false;
690void Qgs3DMapScene::onBackgroundColorChanged()
692 mEngine->setClearColor( mMap.backgroundColor() );
695void Qgs3DMapScene::updateLights()
697 for ( Qt3DCore::QEntity *entity : std::as_const( mLightEntities ) )
698 entity->deleteLater();
699 mLightEntities.clear();
701 QgsFrameGraph *frameGraph = mEngine->frameGraph();
702 const QList<QgsLightSource *> newLights = mMap.lightSources();
703 for (
const QgsLightSource *source : newLights )
705 Qt3DCore::QEntity *entity = source->createEntity( mMap,
this );
707 mLightEntities.append( entity );
710 onShadowSettingsChanged();
713void Qgs3DMapScene::updateCameraLens()
715 mEngine->camera()->lens()->setFieldOfView( mMap.fieldOfView() );
716 mEngine->camera()->lens()->setProjectionType( mMap.projectionType() );
720void Qgs3DMapScene::onLayerRenderer3DChanged()
722 QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
726 removeLayerEntity( layer );
729 addLayerEntity( layer );
732void Qgs3DMapScene::onLayersChanged()
734 QSet<QgsMapLayer *> layersBefore = qgis::listToSet( mLayerEntities.keys() );
735 QList<QgsMapLayer *> layersAdded;
736 const QList<QgsMapLayer *>
layers = mMap.layers();
737 for ( QgsMapLayer *layer :
layers )
739 if ( !layersBefore.contains( layer ) )
741 layersAdded << layer;
745 layersBefore.remove( layer );
750 for ( QgsMapLayer *layer : std::as_const( layersBefore ) )
752 removeLayerEntity( layer );
755 for ( QgsMapLayer *layer : std::as_const( layersAdded ) )
757 addLayerEntity( layer );
763 const QList<QgsMapLayer *>
layers = mLayerEntities.keys();
768 if ( temporalProperties->isActive() )
770 removeLayerEntity( layer );
771 addLayerEntity( layer );
779 Q_ASSERT( sceneNewEntity );
781 mSceneEntities.append( sceneNewEntity );
783 sceneNewEntity->setParent(
this );
785 finalizeNewEntity( sceneNewEntity );
787 connect( sceneNewEntity, &Qgs3DMapSceneEntity::newEntityCreated,
this, [
this]( Qt3DCore::QEntity *entity ) {
788 finalizeNewEntity( entity );
790 updateCameraNearFarPlanes();
800 Q_ASSERT( sceneEntity );
802 mSceneEntities.removeOne( sceneEntity );
804 sceneEntity->deleteLater();
808void Qgs3DMapScene::addLayerEntity(
QgsMapLayer *layer )
820 if ( renderer->
type() ==
"vector"_L1 )
828 mModelVectorLayers.append( layer );
832 else if ( renderer->
type() ==
"rulebased"_L1 )
835 for (
auto rule : rules )
837 const QgsPoint3DSymbol *pointSymbol =
dynamic_cast<const QgsPoint3DSymbol *
>( rule->symbol() );
840 mModelVectorLayers.append( layer );
848 QgsMeshLayer3DRenderer *meshRenderer =
static_cast<QgsMeshLayer3DRenderer *
>( renderer );
849 meshRenderer->
setLayer(
static_cast<QgsMeshLayer *
>( layer ) );
853 QgsMesh3DSymbol *sym = meshRenderer->
symbol()->
clone();
859 QgsPointCloudLayer3DRenderer *pointCloudRenderer =
static_cast<QgsPointCloudLayer3DRenderer *
>( renderer );
860 pointCloudRenderer->
setLayer(
static_cast<QgsPointCloudLayer *
>( layer ) );
864 QgsTiledSceneLayer3DRenderer *tiledSceneRenderer =
static_cast<QgsTiledSceneLayer3DRenderer *
>( renderer );
865 tiledSceneRenderer->
setLayer(
static_cast<QgsTiledSceneLayer *
>( layer ) );
869 auto annotationLayerRenderer = qgis::down_cast<QgsAnnotationLayer3DRenderer *>( renderer );
870 annotationLayerRenderer->setLayer( qobject_cast<QgsAnnotationLayer *>( layer ) );
873 Qt3DCore::QEntity *newEntity = renderer->
createEntity( &mMap );
876 mLayerEntities.insert( layer, newEntity );
878 if ( Qgs3DMapSceneEntity *sceneNewEntity = qobject_cast<Qgs3DMapSceneEntity *>( newEntity ) )
885 newEntity->setParent(
this );
886 finalizeNewEntity( newEntity );
895 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
908 QgsPointCloudLayer *pclayer = qobject_cast<QgsPointCloudLayer *>( layer );
914void Qgs3DMapScene::removeLayerEntity(
QgsMapLayer *layer )
916 Qt3DCore::QEntity *entity = mLayerEntities.take( layer );
918 if ( Qgs3DMapSceneEntity *sceneEntity = qobject_cast<Qgs3DMapSceneEntity *>( entity ) )
926 entity->deleteLater();
933 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
937 mModelVectorLayers.removeAll( layer );
947 QgsPointCloudLayer *pclayer = qobject_cast<QgsPointCloudLayer *>( layer );
954void Qgs3DMapScene::finalizeNewEntity( Qt3DCore::QEntity *newEntity )
957 const QList<QgsGeoTransform *> transforms = newEntity->findChildren<QgsGeoTransform *>();
958 for ( QgsGeoTransform *transform : transforms )
960 transform->setOrigin( mMap.origin() );
964 handleClippingOnEntity( newEntity );
968 const QList<QgsLineMaterial *> childLineMaterials = newEntity->findChildren<QgsLineMaterial *>();
969 for ( QgsLineMaterial *lm : childLineMaterials )
973 lm->setViewportSize( mEngine->size() );
976 const QList<QgsPoint3DBillboardMaterial *> childBillboardMaterials = newEntity->findChildren<QgsPoint3DBillboardMaterial *>();
977 for ( QgsPoint3DBillboardMaterial *bm : childBillboardMaterials )
981 bm->setViewportSize( mEngine->size() );
984 QgsFrameGraph *frameGraph = mEngine->frameGraph();
988 const QVector<Qt3DRender::QLayer *>
layers = newEntity->componentsOfType<Qt3DRender::QLayer>();
998 const QList<Qt3DRender::QMaterial *> childMaterials = newEntity->findChildren<Qt3DRender::QMaterial *>();
999 for ( Qt3DRender::QMaterial *material : childMaterials )
1002 if ( Qt3DExtras::QDiffuseSpecularMaterial *ph = qobject_cast<Qt3DExtras::QDiffuseSpecularMaterial *>( material ) )
1004 if ( ph->diffuse().value<QColor>().alphaF() != 1.0f )
1006 Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( ph->parent() );
1007 if ( entity && !entity->components().contains( transparentLayer ) )
1009 entity->addComponent( transparentLayer );
1030 else if ( QgsPoint3DBillboardMaterial *billboardMaterial = qobject_cast<QgsPoint3DBillboardMaterial *>( material ) )
1032 Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( billboardMaterial->parent() );
1033 if ( entity && !entity->components().contains( transparentLayer ) )
1035 entity->addComponent( transparentLayer );
1042 Qt3DRender::QEffect *effect = material->effect();
1045 const QVector<Qt3DRender::QParameter *> parameters = effect->parameters();
1046 for (
const Qt3DRender::QParameter *parameter : parameters )
1048 if ( parameter->name() ==
"opacity" && parameter->value() != 1.0f )
1050 Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( material->parent() );
1051 if ( entity && !entity->components().contains( transparentLayer ) )
1053 entity->addComponent( transparentLayer );
1063int Qgs3DMapScene::maximumTextureSize()
const
1065 QSurface *surface = mEngine->surface();
1066 QOpenGLContext context;
1068 bool success = context.makeCurrent( surface );
1072 QOpenGLFunctions openglFunctions = QOpenGLFunctions( &context );
1075 openglFunctions.initializeOpenGLFunctions();
1076 openglFunctions.glGetIntegerv( GL_MAX_TEXTURE_SIZE, &size );
1085void Qgs3DMapScene::addCameraViewCenterEntity( Qt3DRender::QCamera *camera )
1087 mEntityCameraViewCenter =
new Qt3DCore::QEntity;
1089 Qt3DCore::QTransform *trCameraViewCenter =
new Qt3DCore::QTransform;
1090 mEntityCameraViewCenter->addComponent( trCameraViewCenter );
1091 connect( camera, &Qt3DRender::QCamera::viewCenterChanged,
this, [trCameraViewCenter, camera] { trCameraViewCenter->setTranslation( camera->viewCenter() ); } );
1093 Qt3DExtras::QPhongMaterial *materialCameraViewCenter =
new Qt3DExtras::QPhongMaterial;
1094 materialCameraViewCenter->setAmbient( Qt::red );
1095 mEntityCameraViewCenter->addComponent( materialCameraViewCenter );
1097 Qt3DExtras::QSphereMesh *rendererCameraViewCenter =
new Qt3DExtras::QSphereMesh;
1098 rendererCameraViewCenter->setRadius( 10 );
1099 mEntityCameraViewCenter->addComponent( rendererCameraViewCenter );
1101 mEntityCameraViewCenter->setEnabled( mMap.showCameraViewCenter() );
1102 mEntityCameraViewCenter->setParent(
this );
1109 if ( mSceneState == state )
1111 mSceneState = state;
1115void Qgs3DMapScene::updateSceneState()
1117 if ( mTerrainUpdateScheduled )
1123 for ( Qgs3DMapSceneEntity *entity : std::as_const( mSceneEntities ) )
1125 if ( entity->isEnabled() && entity->pendingJobsCount() > 0 )
1132 setSceneState(
Ready );
1135void Qgs3DMapScene::onBackgroundSettingsChanged()
1137 const QgsAbstract3DMapBackgroundSettings *settings = mMap.backgroundSettings();
1140 if ( mBackgroundEntity )
1142 mBackgroundEntity->deleteLater();
1143 mBackgroundEntity =
nullptr;
1148 QgsFrameGraph *frameGraph = mEngine->frameGraph();
1152 const QgsSkyboxSettings *skyboxSettings =
dynamic_cast<const QgsSkyboxSettings *
>( settings );
1154 mBackgroundEntity =
new QgsCubeFacesSkyboxEntity( skyboxSettings->
cubeMapping(), faces[u
"posX"_s], faces[u
"posY"_s], faces[u
"posZ"_s], faces[u
"negX"_s], faces[u
"negY"_s], faces[u
"negZ"_s],
this );
1158 const QgsFixedGradientBackgroundSettings *gradientSettings =
dynamic_cast<const QgsFixedGradientBackgroundSettings *
>( settings );
1159 mBackgroundEntity =
new QgsGradientBackgroundEntity( gradientSettings->
topColor(), gradientSettings->
bottomColor(),
this );
1166void Qgs3DMapScene::onShadowSettingsChanged()
1171void Qgs3DMapScene::onAmbientOcclusionSettingsChanged()
1173 mEngine->frameGraph()->updateAmbientOcclusionSettings( mMap.ambientOcclusionSettings() );
1176void Qgs3DMapScene::onDebugShadowMapSettingsChanged()
1178 mEngine->frameGraph()->updateDebugShadowMapSettings( mMap );
1181void Qgs3DMapScene::onDebugDepthMapSettingsChanged()
1183 mEngine->frameGraph()->updateDebugDepthMapSettings( mMap );
1186void Qgs3DMapScene::onDebugOverlayEnabledChanged()
1188 mEngine->frameGraph()->setDebugOverlayEnabled( mMap.isDebugOverlayEnabled() );
1189 mEngine->renderSettings()->setRenderPolicy( mMap.isDebugOverlayEnabled() ? Qt3DRender::QRenderSettings::Always : Qt3DRender::QRenderSettings::OnDemand );
1192void Qgs3DMapScene::onEyeDomeShadingSettingsChanged()
1194 mEngine->frameGraph()->updateEyeDomeSettings( mMap );
1197void Qgs3DMapScene::onMsaaEnabledChanged()
1199 mEngine->frameGraph()->setMsaaEnabled( mMap.isMsaaEnabled() );
1202void Qgs3DMapScene::onShowMapOverlayChanged()
1205 update2DMapOverlay( extent2D );
1208void Qgs3DMapScene::onCameraMovementSpeedChanged()
1210 mCameraController->setCameraMovementSpeed( mMap.cameraMovementSpeed() );
1213void Qgs3DMapScene::onCameraNavigationModeChanged()
1215 mCameraController->setCameraNavigationMode( mMap.cameraNavigationMode() );
1220 QVector<QString> notParsedLayers;
1231 for (
auto it = mLayerEntities.constBegin(); it != mLayerEntities.constEnd(); ++it )
1234 Qt3DCore::QEntity *rootEntity = it.value();
1236 switch ( layerType )
1240 notParsedLayers.push_back( layer->
name() );
1250 notParsedLayers.push_back( layer->
name() );
1264 if ( !notParsedLayers.empty() )
1266 QString message = tr(
"The following layers were not exported:" ) +
"\n";
1267 for (
const QString &layerName : notParsedLayers )
1268 message += layerName +
"\n";
1277 QVector<const QgsChunkNode *> chunks;
1278 if ( !mLayerEntities.contains( layer ) )
1280 if ( QgsChunkedEntity *
c = qobject_cast<QgsChunkedEntity *>( mLayerEntities[layer] ) )
1282 const QList<QgsChunkNode *> activeNodes =
c->activeNodes();
1283 for ( QgsChunkNode *n : activeNodes )
1284 chunks.push_back( n );
1291 return mMap.extent();
1296 double zMin = std::numeric_limits<double>::max();
1297 double zMax = std::numeric_limits<double>::lowest();
1298 if ( mMap.terrainRenderingEnabled() && mTerrain && !ignoreTerrain )
1300 const QgsBox3D box3D = mTerrain->rootNode()->box3D();
1301 zMin = std::min( zMin, box3D.
zMinimum() );
1302 zMax = std::max( zMax, box3D.
zMaximum() );
1305 for (
auto it = mLayerEntities.constBegin(); it != mLayerEntities.constEnd(); it++ )
1308 switch ( layer->
type() )
1314 zMin = std::min( zMin, zRange.
lower() );
1315 zMax = std::max( zMax, zRange.
upper() );
1320 QgsMeshLayer *meshLayer = qobject_cast<QgsMeshLayer *>( layer );
1328 zMin = std::min( zMin, verticalGroupMetadata.
minimum() * verticalScale );
1329 zMax = std::max( zMax, verticalGroupMetadata.
maximum() * verticalScale );
1339 zMin = std::min( zMin, zRange.
lower() );
1340 zMax = std::max( zMax, zRange.
upper() );
1353 const QgsDoubleRange zRange( std::min( zMin, std::numeric_limits<double>::max() ), std::max( zMax, std::numeric_limits<double>::lowest() ) );
1364 mEntityRotationCenter =
new Qt3DCore::QEntity;
1366 Qt3DCore::QTransform *trRotationCenter =
new Qt3DCore::QTransform;
1367 mEntityRotationCenter->addComponent( trRotationCenter );
1368 Qt3DExtras::QPhongMaterial *materialRotationCenter =
new Qt3DExtras::QPhongMaterial;
1369 materialRotationCenter->setAmbient( Qt::blue );
1370 mEntityRotationCenter->addComponent( materialRotationCenter );
1371 Qt3DExtras::QSphereMesh *rendererRotationCenter =
new Qt3DExtras::QSphereMesh;
1372 rendererRotationCenter->setRadius( 10 );
1373 mEntityRotationCenter->addComponent( rendererRotationCenter );
1374 mEntityRotationCenter->setEnabled(
false );
1375 mEntityRotationCenter->setParent(
this );
1382void Qgs3DMapScene::on3DAxisSettingsChanged()
1386 m3DAxis->onAxisSettingsChanged();
1390 if ( QgsWindow3DEngine *
engine =
dynamic_cast<QgsWindow3DEngine *
>( mEngine ) )
1392 m3DAxis =
new Qgs3DAxis(
static_cast<Qgs3DMapCanvas *
>(
engine->window() ),
engine->root(),
this, mCameraController, &mMap );
1397void Qgs3DMapScene::onOriginChanged()
1399 const QList<QgsGeoTransform *> geoTransforms = findChildren<QgsGeoTransform *>();
1400 for ( QgsGeoTransform *transform : geoTransforms )
1402 transform->setOrigin( mMap.origin() );
1405 const QList<QgsGeoTransform *> rubberBandGeoTransforms = mEngine->frameGraph()->rubberBandsRootEntity()->findChildren<QgsGeoTransform *>();
1406 for ( QgsGeoTransform *transform : rubberBandGeoTransforms )
1408 transform->setOrigin( mMap.origin() );
1411 const QgsVector3D oldOrigin = mCameraController->origin();
1412 mCameraController->setOrigin( mMap.origin() );
1414 if ( !mClipPlanesEquations.isEmpty() )
1423 QList<QVector4D> newPlanes;
1424 QgsVector3D originShift = mMap.origin() - oldOrigin;
1425 for ( QVector4D plane : std::as_const( mClipPlanesEquations ) )
1427 plane.setW( originShift.
x() * plane.x() + originShift.
y() * plane.y() + originShift.
z() * plane.z() + plane.w() );
1428 newPlanes.append( plane );
1434void Qgs3DMapScene::handleClippingOnEntity( QEntity *entity )
const
1436 if ( mClipPlanesEquations.isEmpty() )
1438 for ( QgsMaterial *material : entity->componentsOfType<QgsMaterial>() )
1440 material->disableClipping();
1445 for ( QgsMaterial *material : entity->componentsOfType<QgsMaterial>() )
1447 material->enableClipping( mClipPlanesEquations );
1453 for ( QObject *child : entity->children() )
1455 Qt3DCore::QEntity *childEntity = qobject_cast<Qt3DCore::QEntity *>( child );
1458 handleClippingOnEntity( childEntity );
1463void Qgs3DMapScene::handleClippingOnAllEntities()
const
1467 for (
auto it = mLayerEntities.constBegin(); it != mLayerEntities.constEnd(); ++it )
1469 handleClippingOnEntity( it.value() );
1473 handleClippingOnEntity( mTerrain );
1477 handleClippingOnEntity( mGlobe );
1485 QgsDebugMsgLevel( u
"Qgs3DMapScene::enableClipping: it is not possible to use more than %1 clipping planes."_s.arg( mMaxClipPlanes ), 2 );
1493 handleClippingOnAllEntities();
1498 mClipPlanesEquations.clear();
1501 mEngine->frameGraph()->removeClipPlanes();
1504 handleClippingOnAllEntities();
1507void Qgs3DMapScene::onStopUpdatesChanged()
1512void Qgs3DMapScene::schedule2DMapOverlayUpdate()
1515 if ( mMap.is2DMapOverlayEnabled() && mOverlayUpdateTimer && !mOverlayUpdateTimer->isActive() )
1517 mOverlayUpdateTimer->start();
1521void Qgs3DMapScene::applyPendingOverlayUpdate()
1523 if ( mMap.is2DMapOverlayEnabled() )
1526 update2DMapOverlay( extent2D );
@ DistinctTextureSkybox
Skybox with 6 distinct textures for different faces.
@ FixedGradientBackground
Two color gradient, fixed in place.
LayerType
Types of layers that can be added to a map.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
@ Globe
Scene is represented as a globe using a geocentric CRS.
@ Local
Local scene based on a projected CRS.
Manages the various settings the user can choose from when exporting a 3D scene.
bool exportNormals() const
Returns whether normals will be exported.
int terrrainResolution() const
Returns the terrain resolution.
QString sceneFolderPath() const
Returns the scene folder path.
float scale() const
Returns the scale of the exported model.
int terrainTextureResolution() const
Returns the terrain texture resolution.
bool terrainExportEnabled() const
Returns whether terrain export is enabled.
QString sceneName() const
Returns the scene name.
bool smoothEdges() const
Returns whether triangles edges will look smooth.
bool exportTextures() const
Returns whether textures will be exported.
Qgis::Export3DSceneFormat exportFormat() const
Returns the export format for the 3D scene.
void viewed2DExtentFrom3DChanged(QVector< QgsPointXY > extent)
Emitted when the viewed 2D extent seen by the 3D camera has changed.
QList< QVector4D > clipPlaneEquations() const
Returns list of clipping planes if clipping is enabled, otherwise an empty list.
static std::function< QMap< QString, Qgs3DMapScene * >()> sOpenScenesFunction
Static function for returning open 3D map scenes.
void fpsCountChanged(float fpsCount)
Emitted when the FPS count changes.
void setViewFrom2DExtent(const QgsRectangle &extent)
Resets camera view to show the extent extent (top view).
void disableClipping()
Disables OpenGL clipping.
QVector< const QgsChunkNode * > getLayerActiveChunkNodes(QgsMapLayer *layer) SIP_SKIP
Returns the active chunk nodes of layer.
void gpuMemoryLimitReached()
Emitted when one of the entities reaches its GPU memory limit and it is not possible to lower the GPU...
static Q_DECL_DEPRECATED QMap< QString, Qgs3DMapScene * > openScenes() SIP_DEPRECATED
Returns a map of 3D map scenes (by name) open in the QGIS application.
QgsCameraController * cameraController() const
Returns camera controller.
SceneState
Enumeration of possible states of the 3D scene.
@ Ready
The scene is fully loaded/updated.
@ Updating
The scene is still being loaded/updated.
bool exportScene(const Qgs3DMapExportSettings &exportSettings)
Exports the scene according to the scene export settings Returns false if the operation failed.
int totalPendingJobsCount() const
Returns number of pending jobs for all chunked entities.
QList< QgsMapLayer * > layers() const SIP_SKIP
Returns the layers that contain chunked entities.
void addSceneEntity(Qgs3DMapSceneEntity *entity) SIP_SKIP
Adds a 3D map scene entity to the scene.
void updateTemporal()
Updates the temporale entities.
void totalPendingJobsCountChanged()
Emitted when the total number of pending jobs changes.
Qgs3DMapScene(Qgs3DMapSettings &map, QgsAbstract3DEngine *engine) SIP_SKIP
Constructs a 3D scene based on map settings and Qt 3D renderer configuration.
void fpsCounterEnabledChanged(bool fpsCounterEnabled)
Emitted when the FPS counter is activated or deactivated.
void removeSceneEntity(Qgs3DMapSceneEntity *entity) SIP_SKIP
Removes a 3D scene entity for the scene.
QgsDoubleRange elevationRange(bool ignoreTerrain=false) const
Returns the scene's elevation range.
QgsRectangle sceneExtent() const
Returns the scene extent in the map's CRS.
void sceneStateChanged()
Emitted when the scene's state has changed.
QgsAbstract3DEngine * engine() const SIP_SKIP
Returns the abstract 3D engine.
QVector< QgsPointXY > viewFrustum2DExtent() const
Calculates the 2D extent viewed by the 3D camera as the vertices of the viewed trapezoid.
void enableClipping(const QList< QVector4D > &clipPlaneEquations)
Enables OpenGL clipping based on the planes equations defined in clipPlaneEquations.
void terrainEntityChanged()
Emitted when the current terrain entity is replaced by a new one.
void viewZoomFull()
Resets camera view to show the whole scene (top view).
double worldSpaceError(double epsilon, double distance) const
Given screen error (in pixels) and distance from camera (in 3D world coordinates),...
void extentChanged()
Emitted when the 3d view's 2d extent has changed.
void originChanged()
Emitted when the world's origin point has been shifted.
void eyeDomeLightingDistanceChanged()
Emitted when the eye dome lighting distance has changed.
void terrainShadingChanged()
Emitted when terrain shading enabled flag or terrain shading material has changed.
void debugDepthMapSettingsChanged()
Emitted when depth map debugging has changed.
void backgroundSettingsChanged()
Emitted when background settings are changed.
void backgroundColorChanged()
Emitted when the background color has changed.
void showCameraRotationCenterChanged()
Emitted when the flag whether camera's rotation center is shown has changed.
void cameraNavigationModeChanged()
Emitted when the camera navigation mode was changed.
void shadowSettingsChanged()
Emitted when shadow rendering settings are changed.
void show2DMapOverlayChanged()
Emitted when the 2D map overlay is enabled or disabled.
bool stopUpdates() const
Returns whether the scene updates on camera movement.
void eyeDomeLightingEnabledChanged()
Emitted when the flag whether eye dome lighting is used has changed.
void debugOverlayEnabledChanged(bool debugOverlayEnabled)
Emitted when the debug overaly is enabled or disabled.
void setOrigin(const QgsVector3D &origin)
Sets coordinates in map CRS at which our 3D world has origin (0,0,0).
void msaaEnabledChanged()
Emitted when the MSAA enabled flag has changed.
void projectionTypeChanged()
Emitted when the camera lens projection type changes.
void stopUpdatesChanged()
Emitted when the flag whether to keep updating scene has changed.
void lightSourcesChanged()
Emitted when any of the light source settings in the map changes.
void showLightSourceOriginsChanged()
Emitted when the flag whether light source origins are shown has changed.
void terrainSettingsChanged()
Emitted when the terrain settings are changed.
void fpsCounterEnabledChanged(bool fpsCounterEnabled)
Emitted when the FPS counter is enabled or disabled.
void axisSettingsChanged()
Emitted when 3d axis rendering settings are changed.
void viewFrustumVisualizationEnabledChanged()
Emitted when the camera's view frustum visualization on the main 2D map canvas is enabled or disabled...
void ambientOcclusionSettingsChanged()
Emitted when ambient occlusion rendering settings are changed.
void layersChanged()
Emitted when the list of map layers for 3d rendering has changed.
void eyeDomeLightingStrengthChanged()
Emitted when the eye dome lighting strength has changed.
void cameraMovementSpeedChanged()
Emitted when the camera movement speed was changed.
void fieldOfViewChanged()
Emitted when the camera lens field of view changes.
void terrainGeneratorChanged()
Emitted when the terrain generator has changed.
void debugShadowMapSettingsChanged()
Emitted when shadow map debugging has changed.
void showCameraViewCenterChanged()
Emitted when the flag whether camera's view center is shown has changed.
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0).
Entity that handles the exporting of 3D scenes.
void setExportTextures(bool exportTextures)
Sets whether the textures will be exported.
void parseTerrain(QgsTerrainEntity *terrain, const QString &layer)
Creates terrain export objects from the terrain entity.
void setTerrainResolution(int resolution)
Sets the terrain resolution.
void setTerrainTextureResolution(int resolution)
Sets the terrain texture resolution.
bool parseVectorLayerEntity(Qt3DCore::QEntity *entity, QgsVectorLayer *layer)
Creates necessary export objects from entity if it represents valid vector layer entity Returns false...
void setScale(float scale)
Sets the scale of the exported 3D model.
bool save(QString sceneName, QString sceneFolderPath, const Qgis::Export3DSceneFormat &exportFormat=Qgis::Export3DSceneFormat::Obj, int precision=6) const
Saves the scene to a file Returns false if the operation failed.
void setExportNormals(bool exportNormals)
Sets whether the normals will be exported.
void setSmoothEdges(bool smoothEdges)
Sets whether the triangles will look smooth.
void setTerrainExportEnabled(bool enabled)
Sets whether terrain export is enabled.
static int maxZoomLevel(double tile0width, double tileResolution, double maxError)
Calculates the highest needed zoom level for tiles in quad-tree given width of the base tile (zoom le...
static QgsAABB mapToWorldExtent(const QgsRectangle &extent, double zMin, double zMax, const QgsVector3D &mapOrigin)
Converts map extent to axis aligned bounding box in 3D world coordinates.
static void computeBoundingBoxNearFarPlanes(const QgsAABB &bbox, const QMatrix4x4 &viewMatrix, float &fnear, float &ffar)
This routine computes nearPlane farPlane from the closest and farthest corners point of bounding box ...
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.
static int openGlMaxClipPlanes(QSurface *surface)
Gets the maximum number of clip planes that can be used.
Base class for 3D engine implementation.
void sizeChanged()
Emitted after a call to setSize().
virtual Qt3DRender::QCamera * camera()=0
Returns pointer to the engine's camera entity.
virtual Qgis::Map3DBackgroundType type() const =0
Returns the unique type for this background settings class.
Base class for all renderers that participate in 3D views.
virtual QString type() const =0
Returns unique identifier of the renderer class (used to identify subclass).
virtual Qt3DCore::QEntity * createEntity(Qgs3DMapSettings *map) const =0
Returns a 3D entity that will be used to show renderer's data in 3D scene.
virtual void setEnabled(bool enable)
Enable or disable via enable the render view sub tree.
Base class for 3D renderers that are based on vector layers.
static QgsSourceCache * sourceCache()
Returns the application's source cache, used for caching embedded and remote source strings as local ...
A 3-dimensional box composed of x, y, z coordinates.
double zMaximum() const
Returns the maximum z value.
double zMinimum() const
Returns the minimum z value.
Object that controls camera movement based on user input.
Qt3DRender::QCamera * camera() const
Returns camera that is being controlled.
void cameraChanged()
Emitted when camera has been updated.
void cameraRotationCenterChanged(QVector3D position)
Emitted when the camera rotation center changes.
QgsRange which stores a range of double values.
bool isInfinite() const
Returns true if the range consists of all possible values.
QColor topColor() const
Returns the color at the top of the gradient.
QColor bottomColor() const
Returns the color at the bottom of the gradient.
Qt3DRender::QLayer * renderLayer()
Returns a layer object used to indicate that the object is transparent.
Qt3DRender::QLayer * transparentObjectLayer()
Returns a layer object used to indicate that the object is transparent.
Qt3DRender::QLayer * backgroundLayer()
Returns a layer object used for skybox and background gradient entities.
void updateShadowSettings(const QgsShadowSettings &shadowSettings, const QList< QgsLightSource * > &lightSources)
Updates shadow bias, light and texture size according to shadowSettings and lightSources.
QgsHighlightsRenderView & highlightsRenderView()
Returns the highlights renderview, used for rendering highlight overlays of identified features.
QgsForwardRenderView & forwardRenderView()
Returns forward renderview.
QgsOverlayTextureRenderView & overlayTextureRenderView()
Returns overlay texture renderview.
QgsShadowRenderView & shadowRenderView()
Returns shadow renderview.
Qt3DRender::QLayer * highlightsLayer()
Returns a layer that should be attached to entities meant to be rendered by QgsHighlightsRenderView.
virtual QgsDoubleRange calculateZRange(QgsMapLayer *layer) const
Attempts to calculate the overall elevation or z range for the specified layer, using the settings de...
Base class for storage of map layer temporal properties.
Base class for all map layer types.
QgsAbstract3DRenderer * renderer3D() const
Returns 3D renderer associated with the layer.
void request3DUpdate()
Signal emitted when a layer requires an update in any 3D maps.
void renderer3DChanged()
Signal emitted when 3D renderer associated with the layer has changed.
void rendererChanged()
Signal emitted when renderer is changed.
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
void layerModified()
Emitted when modifications has been done on layer.
double verticalScale() const
Returns mesh vertical scale.
int verticalDatasetGroupIndex() const
Returns the index of the dataset group that will be used to render the vertical component of the 3D m...
void setMaximumTextureSize(int maximumTextureSize)
Sets the maximum texture size supported by the hardware Used to store the GL_MAX_TEXTURE_SIZE value t...
QgsMesh3DSymbol * clone() const override SIP_FACTORY
Returns a new instance of the symbol with the same settings.
3D renderer that renders all mesh triangles of a mesh layer.
void setSymbol(QgsMesh3DSymbol *symbol)
Sets 3D symbol associated with the renderer.
const QgsMesh3DSymbol * symbol() const
Returns 3D symbol associated with the renderer.
void setLayer(QgsMeshLayer *layer)
Sets vector layer associated with the renderer.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
virtual void showMessage(bool blocking=true)=0
display the message to the user and deletes itself
3D symbol that draws point geometries as 3D objects using one of the predefined shapes.
Qgis::Point3DShape shape() const
Returns 3D shape for points.
QVariant shapeProperty(const QString &property) const
Returns the value for a specific shape property.
void setLayer(QgsPointCloudLayer *layer)
Sets point cloud layer associated with the renderer.
Represents a map layer supporting display of point clouds.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
void subsetStringChanged()
Emitted when the layer's subset string has changed.
T lower() const
Returns the lower bound of the range.
T upper() const
Returns the upper bound of the range.
bool isEmpty() const
Returns true if the range is empty, ie the lower bound equals (or exceeds) the upper bound and either...
A representation of a ray in 3D.
QVector3D origin() const
Returns the origin of the ray.
QVector3D direction() const
Returns the direction of the ray see setDirection().
A rectangle specified with double values.
static QgsRectangle fromCenterAndSize(const QgsPointXY ¢er, double width, double height)
Creates a new rectangle, given the specified center point and width and height.
A child rule for a QgsRuleBased3DRenderer.
QList< QgsRuleBased3DRenderer::Rule * > RuleList
Qt3DRender::QLayer * entityCastingShadowsLayer() const
Returns the layer to be used by entities to be included in this renderview.
QMap< QString, QString > cubeMapFacesPaths() const
Returns a map containing the path of each texture specified by the user.
Qgis::SkyboxCubeMapping cubeMapping() const
Returns the cube face mapping scheme.
void remoteSourceFetched(const QString &url)
Emitted when the cache has finished retrieving a 3D model from a remote url.
void setLayer(QgsTiledSceneLayer *layer)
Sets tiled scene layer associated with the renderer.
Represents a map layer supporting display of tiled scene objects.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
QString toString(int precision=17) const
Returns a string representation of the 3D vector.
double x() const
Returns X coordinate.
3D renderer that renders all features of a vector layer with the same 3D symbol.
const QgsAbstract3DSymbol * symbol() const
Returns 3D symbol associated with the renderer.
Represents a vector layer which manages a vector based dataset.
void subsetStringChanged()
Emitted when the layer's subset string has changed.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsFloatNear(float a, float b, float epsilon=4 *FLT_EPSILON)
Compare two floats (but allow some difference).
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)