QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsrulebasedchunkloader_p.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrulebasedchunkloader_p.cpp
3  --------------------------------------
4  Date : November 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"
19 #include "qgschunknode_p.h"
20 #include "qgspolygon3dsymbol_p.h"
21 #include "qgseventtracing.h"
22 
23 #include "qgsvectorlayer.h"
25 
26 #include "qgsrulebased3drenderer.h"
27 
28 #include <QtConcurrent>
29 
31 
32 
33 QgsRuleBasedChunkLoader::QgsRuleBasedChunkLoader( const QgsRuleBasedChunkLoaderFactory *factory, QgsChunkNode *node )
34  : QgsChunkLoader( node )
35  , mFactory( factory )
36  , mContext( factory->mMap )
37  , mSource( new QgsVectorLayerFeatureSource( factory->mLayer ) )
38 {
39  if ( node->level() < mFactory->mLeafLevel )
40  {
41  QTimer::singleShot( 0, this, &QgsRuleBasedChunkLoader::finished );
42  return;
43  }
44 
45  QgsVectorLayer *layer = mFactory->mLayer;
46  const Qgs3DMapSettings &map = mFactory->mMap;
47 
49  exprContext.setFields( layer->fields() );
50  mContext.setExpressionContext( exprContext );
51 
52  // factory is shared among multiple loaders which may be run at the same time
53  // so we need a local copy of our rule tree that does not intefere with others
54  // (e.g. it happened that filter expressions with invalid syntax would cause
55  // nasty crashes when trying to simultaneously record evaluation error)
56  mRootRule.reset( mFactory->mRootRule->clone() );
57 
58  mRootRule->createHandlers( layer, mHandlers );
59 
60  QSet<QString> attributeNames;
61  mRootRule->prepare( mContext, attributeNames, mHandlers );
62 
63  // build the feature request
65  req.setDestinationCrs( map.crs(), map.transformContext() );
66  req.setSubsetOfAttributes( attributeNames, layer->fields() );
67 
68  // only a subset of data to be queried
69  QgsRectangle rect = Qgs3DUtils::worldToMapExtent( node->bbox(), map.origin() );
70  req.setFilterRect( rect );
71 
72  //
73  // this will be run in a background thread
74  //
75 
76  QFuture<void> future = QtConcurrent::run( [req, this]
77  {
78  QgsEventTracing::ScopedEvent e( QStringLiteral( "3D" ), QStringLiteral( "RB chunk load" ) );
79 
80  QgsFeature f;
81  QgsFeatureIterator fi = mSource->getFeatures( req );
82  while ( fi.nextFeature( f ) )
83  {
84  if ( mCanceled )
85  break;
86  mContext.expressionContext().setFeature( f );
87  mRootRule->registerFeature( f, mContext, mHandlers );
88  }
89  } );
90 
91  // emit finished() as soon as the handler is populated with features
92  mFutureWatcher = new QFutureWatcher<void>( this );
93  mFutureWatcher->setFuture( future );
94  connect( mFutureWatcher, &QFutureWatcher<void>::finished, this, &QgsChunkQueueJob::finished );
95 }
96 
97 QgsRuleBasedChunkLoader::~QgsRuleBasedChunkLoader()
98 {
99  if ( mFutureWatcher && !mFutureWatcher->isFinished() )
100  {
101  disconnect( mFutureWatcher, &QFutureWatcher<void>::finished, this, &QgsChunkQueueJob::finished );
102  mFutureWatcher->waitForFinished();
103  }
104 
105  qDeleteAll( mHandlers );
106  mHandlers.clear();
107 }
108 
109 void QgsRuleBasedChunkLoader::cancel()
110 {
111  mCanceled = true;
112 }
113 
114 Qt3DCore::QEntity *QgsRuleBasedChunkLoader::createEntity( Qt3DCore::QEntity *parent )
115 {
116  if ( mNode->level() < mFactory->mLeafLevel )
117  {
118  return new Qt3DCore::QEntity( parent ); // dummy entity
119  }
120 
121  float zMin = std::numeric_limits<float>::max();
122  float zMax = std::numeric_limits<float>::min();
123 
124  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity( parent );
125  for ( QgsFeature3DHandler *handler : mHandlers.values() )
126  {
127  handler->finalize( entity, mContext );
128  if ( handler->zMinimum() < zMin )
129  zMin = handler->zMinimum();
130  if ( handler->zMaximum() > zMax )
131  zMax = handler->zMaximum();
132  }
133 
134  // fix the vertical range of the node from the estimated vertical range to the true range
135  if ( zMin != std::numeric_limits<float>::max() && zMax != std::numeric_limits<float>::min() )
136  {
137  QgsAABB box = mNode->bbox();
138  box.yMin = zMin;
139  box.yMax = zMax;
140  mNode->setExactBbox( box );
141  }
142 
143  return entity;
144 }
145 
146 
148 
149 
150 QgsRuleBasedChunkLoaderFactory::QgsRuleBasedChunkLoaderFactory( const Qgs3DMapSettings &map, QgsVectorLayer *vl, QgsRuleBased3DRenderer::Rule *rootRule, int leafLevel )
151  : mMap( map )
152  , mLayer( vl )
153  , mRootRule( rootRule->clone() )
154  , mLeafLevel( leafLevel )
155 {
156 }
157 
158 QgsRuleBasedChunkLoaderFactory::~QgsRuleBasedChunkLoaderFactory() = default;
159 
160 QgsChunkLoader *QgsRuleBasedChunkLoaderFactory::createChunkLoader( QgsChunkNode *node ) const
161 {
162  return new QgsRuleBasedChunkLoader( this, node );
163 }
164 
165 
167 
168 QgsRuleBasedChunkedEntity::QgsRuleBasedChunkedEntity( QgsVectorLayer *vl, double zMin, double zMax, const QgsVectorLayer3DTilingSettings &tilingSettings, QgsRuleBased3DRenderer::Rule *rootRule, const Qgs3DMapSettings &map )
169  : QgsChunkedEntity( Qgs3DUtils::layerToWorldExtent( vl->extent(), zMin, zMax, vl->crs(), map.origin(), map.crs(), map.transformContext() ),
170  -1, // rootError (negative error means that the node does not contain anything)
171  -1, // max. allowed screen error (negative tau means that we need to go until leaves are reached)
172  tilingSettings.zoomLevelsCount() - 1,
173  new QgsRuleBasedChunkLoaderFactory( map, vl, rootRule, tilingSettings.zoomLevelsCount() - 1 ) )
174 {
175  setShowBoundingBoxes( tilingSettings.showBoundingBoxes() );
176 }
177 
178 QgsRuleBasedChunkedEntity::~QgsRuleBasedChunkedEntity()
179 {
180  // cancel / wait for jobs
181  cancelActiveJobs();
182 }
183 
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
QgsRuleBased3DRenderer::Rule::createHandlers
void createHandlers(QgsVectorLayer *layer, RuleToHandlerMap &handlers) const
add handlers
Definition: qgsrulebased3drenderer.cpp:256
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
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
QgsRuleBased3DRenderer::Rule::prepare
void prepare(const Qgs3DRenderContext &context, QSet< QString > &attributeNames, RuleToHandlerMap &handlers) const
call prepare() on handlers and populate attributeNames
Definition: qgsrulebased3drenderer.cpp:288
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:190
QgsAABB::yMin
float yMin
Definition: qgsaabb.h:79
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
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
QgsAABB
Definition: qgsaabb.h:33
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
qgsrulebasedchunkloader_p.h
qgsvectorlayer.h
QgsRuleBased3DRenderer::Rule::registerFeature
RegisterResult registerFeature(QgsFeature &feature, Qgs3DRenderContext &context, RuleToHandlerMap &handlers) const
register individual features
Definition: qgsrulebased3drenderer.cpp:313
qgspolygon3dsymbol_p.h
qgsrulebased3drenderer.h
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:373
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsRuleBased3DRenderer::Rule
Definition: qgsrulebased3drenderer.h:74
QgsVectorLayerFeatureSource
Definition: qgsvectorlayerfeatureiterator.h:51
QgsAABB::yMax
float yMax
Definition: qgsaabb.h:82
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
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
QgsVectorLayer3DTilingSettings
Definition: qgsabstractvectorlayer3drenderer.h:37