QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsvectorlayerchunkloader_p.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerchunkloader_p.cpp
3  --------------------------------------
4  Date : July 2019
5  Copyright : (C) 2019 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 
17 
18 #include "qgs3dutils.h"
20 #include "qgschunknode_p.h"
21 #include "qgspolygon3dsymbol_p.h"
22 #include "qgseventtracing.h"
23 #include "qgslogger.h"
24 #include "qgsvectorlayer.h"
26 
27 #include "qgsline3dsymbol.h"
28 #include "qgspoint3dsymbol.h"
29 #include "qgspolygon3dsymbol.h"
30 
31 #include "qgsline3dsymbol_p.h"
32 #include "qgspoint3dsymbol_p.h"
33 #include "qgspolygon3dsymbol_p.h"
34 
35 #include <QtConcurrent>
36 
38 
39 
40 QgsVectorLayerChunkLoader::QgsVectorLayerChunkLoader( const QgsVectorLayerChunkLoaderFactory *factory, QgsChunkNode *node )
41  : QgsChunkLoader( node )
42  , mFactory( factory )
43  , mContext( factory->mMap )
44  , mSource( new QgsVectorLayerFeatureSource( factory->mLayer ) )
45 {
46  if ( node->level() < mFactory->mLeafLevel )
47  {
48  QTimer::singleShot( 0, this, &QgsVectorLayerChunkLoader::finished );
49  return;
50  }
51 
52  QgsVectorLayer *layer = mFactory->mLayer;
53  const Qgs3DMapSettings &map = mFactory->mMap;
54 
55  QgsFeature3DHandler *handler = nullptr;
56  QString symbolType = mFactory->mSymbol->type();
57  if ( symbolType == QLatin1String( "polygon" ) )
58  handler = Qgs3DSymbolImpl::handlerForPolygon3DSymbol( layer, *static_cast<QgsPolygon3DSymbol *>( mFactory->mSymbol.get() ) );
59  else if ( symbolType == QLatin1String( "point" ) )
60  handler = Qgs3DSymbolImpl::handlerForPoint3DSymbol( layer, *static_cast<QgsPoint3DSymbol *>( mFactory->mSymbol.get() ) );
61  else if ( symbolType == QLatin1String( "line" ) )
62  handler = Qgs3DSymbolImpl::handlerForLine3DSymbol( layer, *static_cast<QgsLine3DSymbol *>( mFactory->mSymbol.get() ) );
63  else
64  {
65  QgsDebugMsg( QStringLiteral( "Unknown 3D symbol type for vector layer: " ) + symbolType );
66  return;
67  }
68  mHandler.reset( handler );
69 
71  exprContext.setFields( layer->fields() );
72  mContext.setExpressionContext( exprContext );
73 
74  QSet<QString> attributeNames;
75  if ( !mHandler->prepare( mContext, attributeNames ) )
76  {
77  QgsDebugMsg( QStringLiteral( "Failed to prepare 3D feature handler!" ) );
78  return;
79  }
80 
81  // build the feature request
83  req.setDestinationCrs( map.crs(), map.transformContext() );
84  req.setSubsetOfAttributes( attributeNames, layer->fields() );
85 
86  // only a subset of data to be queried
87  QgsRectangle rect = Qgs3DUtils::worldToMapExtent( node->bbox(), map.origin() );
88  req.setFilterRect( rect );
89 
90  //
91  // this will be run in a background thread
92  //
93 
94  QFuture<void> future = QtConcurrent::run( [req, this]
95  {
96  QgsEventTracing::ScopedEvent e( QStringLiteral( "3D" ), QStringLiteral( "VL chunk load" ) );
97 
98  QgsFeature f;
99  QgsFeatureIterator fi = mSource->getFeatures( req );
100  while ( fi.nextFeature( f ) )
101  {
102  if ( mCanceled )
103  break;
104  mContext.expressionContext().setFeature( f );
105  mHandler->processFeature( f, mContext );
106  }
107  } );
108 
109  // emit finished() as soon as the handler is populated with features
110  mFutureWatcher = new QFutureWatcher<void>( this );
111  mFutureWatcher->setFuture( future );
112  connect( mFutureWatcher, &QFutureWatcher<void>::finished, this, &QgsChunkQueueJob::finished );
113 }
114 
115 QgsVectorLayerChunkLoader::~QgsVectorLayerChunkLoader()
116 {
117  if ( mFutureWatcher && !mFutureWatcher->isFinished() )
118  {
119  disconnect( mFutureWatcher, &QFutureWatcher<void>::finished, this, &QgsChunkQueueJob::finished );
120  mFutureWatcher->waitForFinished();
121  }
122 }
123 
124 void QgsVectorLayerChunkLoader::cancel()
125 {
126  mCanceled = true;
127 }
128 
129 Qt3DCore::QEntity *QgsVectorLayerChunkLoader::createEntity( Qt3DCore::QEntity *parent )
130 {
131  if ( mNode->level() < mFactory->mLeafLevel )
132  {
133  return new Qt3DCore::QEntity( parent ); // dummy entity
134  }
135 
136  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity( parent );
137  mHandler->finalize( entity, mContext );
138  return entity;
139 }
140 
141 
143 
144 
145 QgsVectorLayerChunkLoaderFactory::QgsVectorLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsVectorLayer *vl, QgsAbstract3DSymbol *symbol, int leafLevel )
146  : mMap( map )
147  , mLayer( vl )
148  , mSymbol( symbol->clone() )
149  , mLeafLevel( leafLevel )
150 {
151 }
152 
153 QgsChunkLoader *QgsVectorLayerChunkLoaderFactory::createChunkLoader( QgsChunkNode *node ) const
154 {
155  return new QgsVectorLayerChunkLoader( this, node );
156 }
157 
158 
160 
161 
162 QgsVectorLayerChunkedEntity::QgsVectorLayerChunkedEntity( QgsVectorLayer *vl, double zMin, double zMax, const QgsVectorLayer3DTilingSettings &tilingSettings, QgsAbstract3DSymbol *symbol, const Qgs3DMapSettings &map )
163  : QgsChunkedEntity( Qgs3DUtils::layerToWorldExtent( vl->extent(), zMin, zMax, vl->crs(), map.origin(), map.crs(), map.transformContext() ),
164  -1, // rootError (negative error means that the node does not contain anything)
165  -1, // max. allowed screen error (negative tau means that we need to go until leaves are reached)
166  tilingSettings.zoomLevelsCount() - 1,
167  new QgsVectorLayerChunkLoaderFactory( map, vl, symbol, tilingSettings.zoomLevelsCount() - 1 ) )
168 {
169  setShowBoundingBoxes( tilingSettings.showBoundingBoxes() );
170 }
171 
172 QgsVectorLayerChunkedEntity::~QgsVectorLayerChunkedEntity()
173 {
174  // cancel / wait for jobs
175  cancelActiveJobs();
176 }
177 
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
Qgs3DMapSettings::crs
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used in the 3D scene.
Definition: qgs3dmapsettings.h:94
qgsline3dsymbol.h
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsVectorLayer3DTilingSettings::showBoundingBoxes
bool showBoundingBoxes() const
Returns whether to display bounding boxes of entity's tiles (for debugging)
Definition: qgsabstractvectorlayer3drenderer.h:58
qgschunknode_p.h
qgsvectorlayerchunkloader_p.h
Qgs3DUtils::worldToMapExtent
static QgsRectangle worldToMapExtent(const QgsAABB &bbox, const QgsVector3D &mapOrigin)
Converts axis aligned bounding box in 3D world coordinates to extent in map coordinates.
Definition: qgs3dutils.cpp:488
QgsPolygon3DSymbol
Definition: qgspolygon3dsymbol.h:36
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:190
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
Qgs3DMapSettings::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Definition: qgs3dmapsettings.cpp:329
QgsRectangle
Definition: qgsrectangle.h:41
QgsFeatureRequest::setFilterRect
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
Definition: qgsfeaturerequest.cpp:97
Qgs3DUtils::globalProjectLayerExpressionContext
static QgsExpressionContext globalProjectLayerExpressionContext(QgsVectorLayer *layer)
Returns expression context for use in preparation of 3D data of a layer.
Definition: qgs3dutils.cpp:566
qgseventtracing.h
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3280
QgsFeatureRequest
Definition: qgsfeaturerequest.h:75
QgsAbstract3DSymbol
Definition: qgsabstract3dsymbol.h:41
QgsAbstractVectorLayer3DRenderer::tilingSettings
QgsVectorLayer3DTilingSettings tilingSettings() const
Returns tiling settings of the renderer.
Definition: qgsabstractvectorlayer3drenderer.h:90
qgs3dutils.h
QgsAbstractVectorLayer3DRenderer::layer
QgsVectorLayer * layer() const
Returns vector layer associated with the renderer.
Definition: qgsabstractvectorlayer3drenderer.cpp:53
qgsabstractvectorlayer3drenderer.h
QgsLine3DSymbol
Definition: qgsline3dsymbol.h:35
Qgs3DMapSettings
Definition: qgs3dmapsettings.h:51
qgsvectorlayerfeatureiterator.h
Qgs3DMapSettings::origin
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
Definition: qgs3dmapsettings.h:84
qgsvectorlayer.h
qgspolygon3dsymbol_p.h
qgspolygon3dsymbol.h
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:373
QgsVectorLayer
Definition: qgsvectorlayer.h:385
qgspoint3dsymbol.h
QgsVectorLayerFeatureSource
Definition: qgsvectorlayerfeatureiterator.h:51
Qgs3DUtils
Definition: qgs3dutils.h:49
QgsFeature
Definition: qgsfeature.h:55
QgsFeatureRequest::setDestinationCrs
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
Definition: qgsfeaturerequest.cpp:263
qgslogger.h
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
qgsline3dsymbol_p.h
qgspoint3dsymbol_p.h
QgsVectorLayer3DTilingSettings
Definition: qgsabstractvectorlayer3drenderer.h:37
QgsPoint3DSymbol
Definition: qgspoint3dsymbol.h:37