28#include <QDomDocument> 
   46  mValues.resize( context.
painter()->device()->width() * context.
painter()->device()->height() / ( mRenderQuality * mRenderQuality ) );
 
   48  mCalculatedMaxValue = 0;
 
   49  mFeaturesRendered = 0;
 
   50  mRadiusPixels = std::round( context.
convertToPainterUnits( mRadius, mRadiusUnit, mRadiusMapUnitScale ) / mRenderQuality );
 
   51  mRadiusSquared = mRadiusPixels * mRadiusPixels;
 
   64  mWeightAttrNum = fields.
lookupField( mWeightExpressionString );
 
   65  if ( mWeightAttrNum == -1 )
 
   67    mWeightExpression.reset( 
new QgsExpression( mWeightExpressionString ) );
 
   74    mExplicitMax = dataDefinedExplicitMax;
 
   78    mRadius = dataDefinedRadius;
 
   80  initializeValues( context );
 
 
  102  Q_UNUSED( drawVertexMarker )
 
  116  if ( !mWeightExpressionString.isEmpty() )
 
  119    if ( mWeightAttrNum == -1 )
 
  121      Q_ASSERT( mWeightExpression.get() );
 
  127      value = attrs.value( mWeightAttrNum );
 
  130    const double evalWeight = value.toDouble( &ok );
 
  137  const int width = context.
painter()->device()->width() / mRenderQuality;
 
  138  const int height = context.
painter()->device()->height() / mRenderQuality;
 
  152  for ( QgsMultiPointXY::const_iterator pointIt = multiPoint.constBegin(); pointIt != multiPoint.constEnd(); ++pointIt )
 
  155    const int pointX = pixel.
x() / mRenderQuality;
 
  156    const int pointY = pixel.
y() / mRenderQuality;
 
  157    for ( 
int x = std::max( pointX - mRadiusPixels, 0 ); x < std::min( pointX + mRadiusPixels, width ); ++x )
 
  162      for ( 
int y = std::max( pointY - mRadiusPixels, 0 ); y < std::min( pointY + mRadiusPixels, height ); ++y )
 
  164        const int index = y * width + x;
 
  165        if ( index >= mValues.count() )
 
  169        const double distanceSquared = std::pow( pointX - x, 2.0 ) + std::pow( pointY - y, 2.0 );
 
  170        if ( distanceSquared > mRadiusSquared )
 
  175        const double score = weight * quarticKernel( std::sqrt( distanceSquared ), mRadiusPixels );
 
  176        const double value = mValues.at( index ) + score;
 
  177        if ( value > mCalculatedMaxValue )
 
  179          mCalculatedMaxValue = value;
 
  181        mValues[ index ] = value;
 
  189  if ( mFeaturesRendered % 200  == 0 )
 
  191    renderImage( context );
 
 
  198double QgsHeatmapRenderer::uniformKernel( 
const double distance, 
const int bandwidth )
 const 
  201  Q_UNUSED( bandwidth )
 
  205double QgsHeatmapRenderer::quarticKernel( 
const double distance, 
const int bandwidth )
 const 
  207  return std::pow( 1. - std::pow( distance / 
static_cast< double >( bandwidth ), 2 ), 2 );
 
  210double QgsHeatmapRenderer::triweightKernel( 
const double distance, 
const int bandwidth )
 const 
  212  return std::pow( 1. - std::pow( distance / 
static_cast< double >( bandwidth ), 2 ), 3 );
 
  215double QgsHeatmapRenderer::epanechnikovKernel( 
const double distance, 
const int bandwidth )
 const 
  217  return ( 1. - std::pow( distance / 
static_cast< double >( bandwidth ), 2 ) );
 
  220double QgsHeatmapRenderer::triangularKernel( 
const double distance, 
const int bandwidth )
 const 
  222  return ( 1. - ( distance / 
static_cast< double >( bandwidth ) ) );
 
  229  renderImage( context );
 
  230  mWeightExpression.reset();
 
 
  240  QImage image( context.
painter()->device()->width() / mRenderQuality,
 
  241                context.
painter()->device()->height() / mRenderQuality,
 
  242                QImage::Format_ARGB32 );
 
  243  image.fill( Qt::transparent );
 
  245  const double scaleMax = mExplicitMax > 0 ? mExplicitMax : mCalculatedMaxValue;
 
  250  for ( 
int heightIndex = 0; heightIndex < image.height(); ++heightIndex )
 
  255    QRgb *scanLine = 
reinterpret_cast< QRgb * 
>( image.scanLine( heightIndex ) );
 
  256    for ( 
int widthIndex = 0; widthIndex < image.width(); ++widthIndex )
 
  259      pixVal = mValues.at( idx ) > 0 ? std::min( ( mValues.at( idx ) / scaleMax ), 1.0 ) : 0;
 
  262      pixColor = mGradientRamp->
color( pixVal );
 
  264      scanLine[widthIndex] = pixColor.rgba();
 
  269  if ( mRenderQuality > 1 )
 
  271    const QImage resized = image.scaled( context.
painter()->device()->width(),
 
  272                                         context.
painter()->device()->height() );
 
  273    context.
painter()->drawImage( 0, 0, resized );
 
  277    context.
painter()->drawImage( 0, 0, image );
 
  283  return QStringLiteral( 
"[HEATMAP]" );
 
 
  309  const double extension = context.
convertToMapUnits( mRadius, mRadiusUnit, mRadiusMapUnitScale );
 
 
  320  r->
setRadius( element.attribute( QStringLiteral( 
"radius" ), QStringLiteral( 
"50.0" ) ).toFloat() );
 
  323  r->
setMaximumValue( element.attribute( QStringLiteral( 
"max_value" ), QStringLiteral( 
"0.0" ) ).toFloat() );
 
  324  r->
setRenderQuality( element.attribute( QStringLiteral( 
"quality" ), QStringLiteral( 
"0" ) ).toInt() );
 
  327  QDomElement sourceColorRampElem = element.firstChildElement( QStringLiteral( 
"colorramp" ) );
 
  328  if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral( 
"name" ) ) == QLatin1String( 
"[source]" ) )
 
 
  343  rendererElem.setAttribute( QStringLiteral( 
"type" ), QStringLiteral( 
"heatmapRenderer" ) );
 
  344  rendererElem.setAttribute( QStringLiteral( 
"radius" ), QString::number( mRadius ) );
 
  345  rendererElem.setAttribute( QStringLiteral( 
"radius_unit" ), QString::number( 
static_cast< int >( mRadiusUnit ) ) );
 
  347  rendererElem.setAttribute( QStringLiteral( 
"max_value" ), QString::number( mExplicitMax ) );
 
  348  rendererElem.setAttribute( QStringLiteral( 
"quality" ), QString::number( mRenderQuality ) );
 
  349  rendererElem.setAttribute( QStringLiteral( 
"weight_expression" ), mWeightExpressionString );
 
  354    rendererElem.appendChild( colorRampElem );
 
  356  mLegendSettings.
writeXml( doc, rendererElem, context );
 
 
  376  QSet<QString> attributes;
 
  382  attributes << mWeightExpressionString;
 
 
  393  if ( renderer->
type() == QLatin1String( 
"heatmapRenderer" ) )
 
  399    auto res = std::make_unique< QgsHeatmapRenderer >();
 
  401    return res.release();
 
 
  421                                mGradientRamp->
clone(),
 
 
  430  delete mGradientRamp;
 
  431  mGradientRamp = ramp;
 
 
  436  mLegendSettings = settings;
 
 
RenderUnit
Rendering size units.
 
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
 
Settings for a color ramp legend node.
 
void setMaximumLabel(const QString &label)
Sets the label for the maximum value on the ramp.
 
void readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads settings from an XML element.
 
void writeXml(QDomDocument &doc, QDomElement &element, const QgsReadWriteContext &context) const
Writes settings to an XML element.
 
void setMinimumLabel(const QString &label)
Sets the label for the minimum value on the ramp.
 
A legend node which renders a color ramp.
 
Abstract base class for color ramps.
 
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
 
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
 
Handles parsing and evaluation of expressions (formerly called "search strings").
 
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
 
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
 
Abstract base class for all 2D vector feature renderers.
 
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the renderer's property collection, used for data defined overrides.
 
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
 
@ HeatmapRadius
Heatmap renderer radius.
 
@ HeatmapMaximum
Heatmap maximum value.
 
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
 
void saveRendererData(QDomDocument &doc, QDomElement &element, const QgsReadWriteContext &context)
Saves generic renderer data into the specified element.
 
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
 
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
bool hasGeometry() const
Returns true if the feature has an associated geometry.
 
Container of fields for a vector layer.
 
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
 
A geometry is the spatial representation of a feature.
 
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
 
QgsMultiPointXY asMultiPoint() const
Returns the contents of the geometry as a multi-point.
 
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
 
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
 
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
 
A renderer which draws points as a live heatmap.
 
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp to use for shading the heatmap.
 
QgsSymbol * symbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
To be overridden.
 
void modifyRequestExtent(QgsRectangle &extent, QgsRenderContext &context) override
Allows for a renderer to modify the extent of a feature request prior to rendering.
 
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
 
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
 
void setRadius(const double radius)
Sets the radius for the heatmap.
 
void setLegendSettings(const QgsColorRampLegendNodeSettings &settings)
Sets the color ramp legend settings.
 
void setRadiusUnit(const Qgis::RenderUnit unit)
Sets the units used for the heatmap's radius.
 
static QgsFeatureRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates a new heatmap renderer instance from XML.
 
void setRenderQuality(const int quality)
Sets the render quality used for drawing the heatmap.
 
bool renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false) override
Render a feature using this renderer in the given context.
 
~QgsHeatmapRenderer() override
 
static QgsHeatmapRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
 
void setWeightExpression(const QString &expression)
Sets the expression used for weighting points when generating the heatmap.
 
void setMaximumValue(const double value)
Sets the maximum value used for shading the heatmap.
 
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
 
QString dump() const override
Returns debug information about this renderer.
 
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
Stores renderer properties to an XML element.
 
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) const override
Returns a list of legend nodes to be used for the legend for the renderer.
 
QgsHeatmapRenderer * clone() const override
Create a deep copy of this renderer.
 
const QgsColorRampLegendNodeSettings & legendSettings() const
Returns the color ramp legend settings.
 
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
 
void setRadiusMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale used for the heatmap's radius.
 
QgsSymbolList symbols(QgsRenderContext &context) const override
Returns list of symbols used by the renderer.
 
Layer tree node points to a map layer.
 
QgsPointXY transform(const QgsPointXY &p) const
Transforms a point p from map (world) coordinates to device coordinates.
 
A container for the context for various read/write operations on objects.
 
A rectangle specified with double values.
 
void setYMinimum(double y)
Set the minimum y value.
 
void setXMinimum(double x)
Set the minimum x value.
 
void setYMaximum(double y)
Set the maximum y value.
 
void setXMaximum(double x)
Set the maximum x value.
 
Contains information about the context of a rendering operation.
 
double convertToMapUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
 
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
 
QPainter * painter()
Returns the destination QPainter for the render operation.
 
QgsExpressionContext & expressionContext()
Gets the expression context.
 
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
 
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
 
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
 
A color ramp entity for QgsStyle databases.
 
An interface for classes which can visit style entity (e.g.
 
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
 
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
 
static std::unique_ptr< QgsColorRamp > loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
 
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
 
static QDomElement saveColorRamp(const QString &name, const QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
 
Abstract base class for all rendered symbols.
 
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
 
#define RENDERER_TAG_NAME
 
QList< QgsSymbol * > QgsSymbolList
 
Contains information relating to the style entity currently being visited.