32#include "moc_qgsmaphittest.cpp"
37 mSettings.setLayerFilterExpressions( layerFilterExpression );
38 mSettings.setFilterPolygon( polygon );
44 mSettings.setLayerFilterExpressions( layerFilterExpression );
49 : mSettings( settings )
60 tmpImage.setDotsPerMeterX(
static_cast< int >( std::round( mapSettings.
outputDpi() * 25.4 ) ) );
61 tmpImage.setDotsPerMeterY(
static_cast< int >( std::round( mapSettings.
outputDpi() * 25.4 ) ) );
62 QPainter painter( &tmpImage );
67 const QList< QgsMapLayer * > layers = mSettings.layers();
74 if ( !layer->isInScaleRange( mapSettings.
scale() ) )
79 extent = mSettings.combinedVisibleExtentForLayer( layer );
85 if (
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
87 if ( !vl->renderer() )
91 SymbolSet &usedSymbols = mHitTest[vl->id()];
92 SymbolSet &usedSymbolsRuleKey = mHitTestRuleKey[vl->id()];
98 auto source = std::make_unique< QgsVectorLayerFeatureSource >( vl );
99 runHitTestFeatureSource( source.get(),
100 vl->id(), vl->fields(), vl->renderer(),
101 usedSymbols, usedSymbolsRuleKey, context,
104 else if (
QgsRasterLayer *rl = qobject_cast<QgsRasterLayer *>( layer ) )
106 if ( !rl->renderer() || !rl->dataProvider() )
111 runHitTestRasterSource( rl->dataProvider(), rl->id(), rl->renderer()->inputBand(), minMaxOrigin, minMaxOrigin.
limits(),
112 context,
nullptr, extent );
114 else if (
QgsMeshLayer *ml = qobject_cast<QgsMeshLayer *>( layer ) )
119 runHitTestMeshSource( ml, ml->id(), datasetIndex, context,
nullptr, extent );
128 return mHitTestRuleKey;
132QMap<QString, QList<QString> > QgsMapHitTest::resultsPy()
const
134 QMap<QString, QList<QString> > res;
135 for (
auto it = mHitTestRuleKey.begin(); it != mHitTestRuleKey.end(); ++it )
137 res.insert( it.key(), qgis::setToList( it.value() ) );
145 if ( !symbol || !layer )
148 auto it = mHitTest.constFind( layer->
id() );
149 if ( it == mHitTest.constEnd() )
160 auto it = mHitTestRuleKey.constFind( layer->
id() );
161 if ( it == mHitTestRuleKey.constEnd() )
164 return it->contains( ruleKey );
168 const QString &layerId,
171 SymbolSet &usedSymbols,
172 SymbolSet &usedSymbolsRuleKey,
177 std::unique_ptr< QgsFeatureRenderer > r( renderer->
clone() );
179 r->startRender( context, fields );
182 if ( r->canSkipRender() )
184 r->stopRender( context );
189 QSet< QString > remainingKeysToFind = r->legendKeys();
190 if ( remainingKeysToFind.empty() )
192 r->stopRender( context );
196 QgsFeatureRequest request;
200 const QString rendererFilterExpression = r->filter( fields );
201 if ( !rendererFilterExpression.isEmpty() )
208 QSet<QString> requiredAttributes = r->usedAttributes( context );
210 QgsGeometry transformedPolygon = visibleExtent;
213 transformedPolygon = QgsGeometry();
218 r->stopRender( context );
222 const QMap<QString, QString> layerFilterExpressions = mSettings.layerFilterExpressions();
223 if (
auto it = layerFilterExpressions.constFind( layerId ); it != layerFilterExpressions.constEnd() )
225 const QString expression = *it;
226 QgsExpression expr( expression );
229 requiredAttributes.unite( expr.referencedColumns() );
235 std::unique_ptr< QgsGeometryEngine > polygonEngine;
238 if ( transformedPolygon.
isNull() )
247 polygonEngine->prepareGeometry();
253 r->stopRender( context );
257 QgsFeatureIterator fi = source->
getFeatures( request );
260 usedSymbolsRuleKey.clear();
281 const QSet< QString > legendKeysForFeature = r->legendKeysForFeature( f, context );
282 for (
const QString &legendKey : legendKeysForFeature )
284 usedSymbolsRuleKey.insert( legendKey );
285 remainingKeysToFind.remove( legendKey );
288 if ( moreSymbolsPerFeature )
290 const QgsSymbolList originalSymbolsForFeature = r->originalSymbolsForFeature( f, context );
291 for ( QgsSymbol *s : originalSymbolsForFeature )
299 QgsSymbol *s = r->originalSymbolForFeature( f, context );
304 if ( remainingKeysToFind.empty() )
310 r->stopRender( context );
314 const QString &layerId,
325 QgsRectangle transformedExtent;
328 transformedExtent = context.
extent();
335 double min = std::numeric_limits<double>::quiet_NaN();
336 double max = std::numeric_limits<double>::quiet_NaN();
339 switch ( minMaxOrigin.
extent() )
358 mHitTestRenderersUpdatedCanvas.insert( layerId, std::pair<double, double>( min, max ) );
362void QgsMapHitTest::runHitTestMeshSource(
QgsMeshLayer *layer,
363 const QString &layerId,
372 QgsRectangle transformedExtent;
375 transformedExtent = context.
extent();
385 double min = std::numeric_limits<double>::quiet_NaN();
386 double max = std::numeric_limits<double>::quiet_NaN();
391 switch ( rangeExtent )
395 switch ( rangeLimit )
415 mHitTestRenderersUpdatedCanvas.insert( layerId, std::pair<double, double>( min, max ) );
425 , mSettings( settings )
436QMap<QString, QList<QString> > QgsMapHitTestTask::resultsPy()
const
438 QMap<QString, QList<QString> > res;
439 for (
auto it = mResults.begin(); it != mResults.end(); ++it )
441 res.insert( it.key(), qgis::setToList( it.value() ) );
447void QgsMapHitTestTask::prepare()
449 const QgsMapSettings &mapSettings = mSettings.mapSettings();
451 const QList< QgsMapLayer * > layers = mSettings.layers();
455 for ( QgsMapLayer *layer : layers )
465 extent = mSettings.combinedVisibleExtentForLayer( layer );
468 if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
470 if ( !vl->renderer() )
473 QgsMapLayerStyleOverride styleOverride( vl );
477 PreparedLayerData layerData;
478 layerData.source = std::make_unique< QgsVectorLayerFeatureSource >( vl );
479 layerData.layerId = vl->id();
480 layerData.fields = vl->fields();
481 layerData.renderer.reset( vl->renderer()->clone() );
483 layerData.extent = extent;
486 mPreparedData.emplace_back( std::move( layerData ) );
488 else if ( QgsRasterLayer *rl = qobject_cast<QgsRasterLayer *>( layer ) )
490 if ( !rl->dataProvider() || !rl->renderer() )
493 QgsRasterMinMaxOrigin minMaxOrigin = rl->renderer()->minMaxOrigin();
495 PreparedRasterData rasterData;
496 rasterData.provider = std::unique_ptr< QgsRasterDataProvider >( rl->dataProvider()->clone() );
497 rasterData.provider->moveToThread(
nullptr );
499 rasterData.layerId = rl->id();
500 rasterData.band = rl->renderer()->inputBand();
501 rasterData.minMaxOrigin = minMaxOrigin;
502 rasterData.rangeLimit = minMaxOrigin.
limits();
504 rasterData.extent = extent;
506 mPreparedRasterData.emplace_back( std::move( rasterData ) );
508 else if ( QgsMeshLayer *ml = qobject_cast<QgsMeshLayer *>( layer ) )
510 PreparedMeshData meshData;
511 meshData.layer = std::unique_ptr< QgsMeshLayer >( ml->clone() );
512 meshData.layer->moveToThread(
nullptr );
514 meshData.layerId = ml->id();
515 meshData.datasetIndex = ml->activeScalarDatasetIndex( context );
517 meshData.extent = extent;
519 mPreparedMeshData.emplace_back( std::move( meshData ) );
534 mFeedback = std::make_unique< QgsFeedback >();
537 auto hitTest = std::make_unique< QgsMapHitTest >( mSettings );
543 tmpImage.setDotsPerMeterX(
static_cast< int >( std::round( mapSettings.
outputDpi() * 25.4 ) ) );
544 tmpImage.setDotsPerMeterY(
static_cast< int >( std::round( mapSettings.
outputDpi() * 25.4 ) ) );
545 QPainter painter( &tmpImage );
551 std::size_t layerIdx = 0;
552 const std::size_t totalCount = mPreparedData.size() + mPreparedRasterData.size() + mPreparedMeshData.size();
554 for (
auto &layerData : mPreparedData )
556 mFeedback->setProgress(
static_cast< double >( layerIdx ) /
static_cast< double >( totalCount ) * 100.0 );
557 if ( mFeedback->isCanceled() )
560 QgsMapHitTest::SymbolSet &usedSymbols = hitTest->mHitTest[layerData.layerId];
561 QgsMapHitTest::SymbolSet &usedSymbolsRuleKey = hitTest->mHitTestRuleKey[layerData.layerId];
564 context.
setExtent( layerData.extent.boundingBox() );
569 hitTest->runHitTestFeatureSource( layerData.source.get(),
572 layerData.renderer.get(),
582 for ( PreparedRasterData &rasterData : mPreparedRasterData )
584 rasterData.provider->moveToThread( QThread:: currentThread() );
586 mFeedback->setProgress( (
static_cast<double>( mPreparedData.size() ) +
static_cast< double >( layerIdx ) ) /
static_cast< double >( totalCount ) * 100.0 );
587 if ( mFeedback->isCanceled() )
591 context.
setExtent( rasterData.extent.boundingBox() );
593 hitTest->runHitTestRasterSource( rasterData.provider.get(),
596 rasterData.minMaxOrigin,
597 rasterData.rangeLimit,
605 for ( PreparedMeshData &meshData : mPreparedMeshData )
607 mFeedback->setProgress( (
static_cast<double>( mPreparedData.size() ) +
static_cast<double>( mPreparedRasterData.size() ) +
static_cast< double >( layerIdx ) ) /
static_cast< double >( totalCount ) * 100.0 );
608 if ( mFeedback->isCanceled() )
612 context.
setExtent( meshData.extent.boundingBox() );
614 meshData.layer->moveToThread( QThread:: currentThread() );
615 meshData.layer->updateTriangularMesh();
617 hitTest->runHitTestMeshSource( meshData.layer.get(),
619 meshData.datasetIndex,
626 mResults = hitTest->mHitTestRuleKey;
628 mResultsRenderersUpdatedCanvas = hitTest->mHitTestRenderersUpdatedCanvas;
635 mPreparedRasterData.clear();
637 mPreparedMeshData.clear();
MeshRangeLimit
Describes the limits used to compute mesh ranges (min/max values).
@ MinimumMaximum
Real min-max values.
RasterRangeLimit
Describes the limits used to compute raster ranges (min/max values).
@ SkipVisibilityCheck
If set, the standard visibility check should be skipped.
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
MeshRangeExtent
Describes the extent used to compute mesh ranges (min/max values).
@ UpdatedCanvas
Constantly updated extent of the canvas is used to compute statistics.
@ WholeMesh
Whole mesh is used to compute statistics.
@ FixedCanvas
Current extent of the canvas (at the time of computation) is used to compute statistics.
@ UpdatedCanvas
Constantly updated extent of the canvas is used to compute statistics.
@ WholeRaster
Whole raster is used to compute statistics.
@ FixedCanvas
Current extent of the canvas (at the time of computation) is used to compute statistics.
Base class that can be used for any class that is capable of returning features.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())=0
Gets an iterator for features matching the specified request.
RAII class to pop scope from an expression context on destruction.
Single scope for storing variables and functions for use within a QgsExpressionContext.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Abstract base class for all 2D vector feature renderers.
@ MoreSymbolsPerFeature
May use more than one symbol to render a feature: symbolsForFeature() will return them.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & combineFilterExpression(const QString &expression)
Modifies the existing filter expression to add an additional expression filter.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Contains settings relating to filtering the contents of QgsLayerTreeModel and views.
QMap< QString, QSet< QString > > results() const
Returns the hit test results, which are a map of layer ID to visible symbol legend keys.
QgsMapHitTestTask(const QgsLayerTreeFilterSettings &settings)
Constructor for QgsMapHitTestTask, using the specified filter settings.
bool run() override
Performs the task's operation.
PRIVATE void cancel() override
Notifies the task that it should terminate.
void run()
Runs the map hit test.
bool symbolVisible(QgsSymbol *symbol, QgsVectorLayer *layer) const
Tests whether a symbol is visible for a specified layer.
bool legendKeyVisible(const QString &ruleKey, QgsVectorLayer *layer) const
Tests whether a given legend key is visible for a specified layer.
QgsMapHitTest(const QgsMapSettings &settings, const QgsGeometry &polygon=QgsGeometry(), const QgsMapHitTest::LayerFilterExpression &layerFilterExpression=QgsMapHitTest::LayerFilterExpression())
Constructor for QgsMapHitTest.
QMap< QString, QSet< QString > > results() const
Returns the hit test results, which are a map of layer ID to visible symbol legend keys.
QMap< QString, QString > LayerFilterExpression
Maps an expression string to a layer id.
Restore overridden layer style on destruction.
void setOverrideStyle(const QString &style)
Temporarily apply a different style to the layer.
Base class for all map layer types.
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
Contains configuration for rendering maps.
double scale() const
Returns the calculated map scale.
QgsCoordinateTransform layerTransform(const QgsMapLayer *layer) const
Returns the coordinate transform from layer's CRS to destination CRS.
QSize outputSize() const
Returns the size of the resulting map image, in pixels.
QImage::Format outputImageFormat() const
format of internal QImage, default QImage::Format_ARGB32_Premultiplied
double outputDpi() const
Returns the DPI (dots per inch) used for conversion between real world units (e.g.
QMap< QString, QString > layerStyleOverrides() const
Returns the map of map layer style overrides (key: layer ID, value: style name) where a different sty...
An index that identifies the dataset group (e.g.
bool isValid() const
Returns whether index is valid, ie at least groups is set.
int group() const
Returns a group index.
int dataset() const
Returns a dataset index within group().
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QgsMeshRendererSettings rendererSettings() const
Returns renderer settings.
bool minimumMaximumActiveScalarDataset(const QgsRectangle &extent, const QgsMeshDatasetIndex &datasetIndex, double &min, double &max)
Extracts minimum and maximum value for active scalar dataset on mesh faces.
Represents a mesh renderer settings for scalar datasets.
Qgis::MeshRangeExtent extent() const
Returns the mesh extent for minimum maximum calculation.
Qgis::MeshRangeLimit limits() const
Returns the range limits type for minimum maximum calculation.
QgsMeshRendererScalarSettings scalarSettings(int groupIndex) const
Returns renderer settings.
Base class for raster data providers.
QgsRectangle extent() const override=0
Returns the extent of the layer.
static void computeMinMax(QgsRasterDataProvider *provider, int band, const QgsRasterMinMaxOrigin &mmo, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, double &min, double &max)
Compute the min max values for provider along band according to MinMaxOrigin parameters mmo and exten...
Represents a raster layer.
static const double SAMPLE_SIZE
Default sample size (number of pixels) for estimated statistics/histogram calculation.
Describes the origin of minimum and maximum values in a raster.
Qgis::RasterRangeExtent extent() const
Returns the raster extent.
Qgis::RasterRangeLimit limits() const
Returns the raster limits.
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
Contains information about the context of a rendering operation.
void setCoordinateTransform(const QgsCoordinateTransform &t)
Sets the current coordinate transform for the context.
QgsExpressionContext & expressionContext()
Gets the expression context.
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
void setExtent(const QgsRectangle &extent)
When rendering a map layer, calling this method sets the "clipping" extent for the layer (in the laye...
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
Abstract base class for all rendered symbols.
void progressChanged(double progress)
Will be emitted by task when its progress changes.
virtual void cancel()
Notifies the task that it should terminate.
QgsTask(const QString &description=QString(), QgsTask::Flags flags=AllFlags)
Constructor for QgsTask.
@ CanCancel
Task can be canceled.
@ CancelWithoutPrompt
Task can be canceled without any users prompts, e.g. when closing a project or QGIS.
@ Silent
Don't show task updates (such as completion/failure messages) as operating-system level notifications...
Represents a vector layer which manages a vector based dataset.
QList< QgsSymbol * > QgsSymbolList