37#include "moc_qgshighlight.cpp"
39using namespace Qt::StringLiterals;
74void QgsHighlight::init()
76 mOriginalGeometry = mGeometry.
isNull() ? mFeature.
geometry() : mGeometry;
80 updateTransformedGeometry();
84 mRenderContext = createRenderContext();
88void QgsHighlight::updateTransformedGeometry()
90 const QgsCoordinateTransform ct =
mMapCanvas->mapSettings().layerTransform( mLayer );
94 if ( ct.
isValid() && !mGeometry.isNull() )
97 mGeometry = mOriginalGeometry;
100 mGeometry.transform( ct );
102 catch ( QgsCsException & )
104 QgsDebugError( u
"Could not transform highlight geometry to canvas CRS"_s );
116 mPen.setColor(
color );
119 mBrush.setStyle( Qt::SolidPattern );
126 mBrush.setStyle( Qt::SolidPattern );
129std::unique_ptr<QgsFeatureRenderer> QgsHighlight::createRenderer(
QgsRenderContext &context,
const QColor &color,
const QColor &fillColor )
131 std::unique_ptr<QgsFeatureRenderer> renderer;
140 for ( QgsSymbol *symbol : symbols )
150void QgsHighlight::setSymbol(
QgsSymbol *symbol,
const QgsRenderContext &context,
const QColor &color,
const QColor &fillColor )
157 QgsSymbolLayer *symbolLayer = symbol->
symbolLayer( i );
172 QgsSimpleMarkerSymbolLayer *simpleMarker =
dynamic_cast<QgsSimpleMarkerSymbolLayer *
>( symbolLayer );
177 QgsSimpleLineSymbolLayer *simpleLine =
dynamic_cast<QgsSimpleLineSymbolLayer *
>( symbolLayer );
182 QgsSimpleFillSymbolLayer *simpleFill =
dynamic_cast<QgsSimpleFillSymbolLayer *
>( symbolLayer );
199 const double adjustedWidthInPainterUnits = std::max( widthInPainterUnits + 2 * bufferInPainterUnits, minWidthInPainterUnits );
206 mPen.setWidth(
width );
220 case QgsHighlight::Square:
222 const double xMax = xMin + 2 * radius;
223 const double yMax = yMin + 2 * radius;
224 QPolygonF r( QVector<QPointF> { QPointF( xMin, yMin ), QPointF( xMax, yMin ), QPointF( xMax, yMax ), QPointF( xMin, yMax ), QPointF( xMin, yMin ) } );
225 context.
painter()->drawPolygon( r );
229 case QgsHighlight::Circle:
231 context.
painter()->drawEllipse( QRectF( xMin, yMin, radius * 2, radius * 2 ) );
237void QgsHighlight::paintLine( QPainter *p,
QgsPolylineXY line )
239 QPolygonF polygon( line.size() );
241 for (
int i = 0; i < line.size(); i++ )
246 p->drawPolyline( polygon );
249void QgsHighlight::paintPolygon( QPainter *p,
const QgsPolygonXY &polygon )
255 p->setBrush( mBrush );
257 for (
const auto &sourceRing : polygon )
259 if ( sourceRing.empty() )
263 ring.reserve( sourceRing.size() + 1 );
266 for (
const auto &sourceVertex : sourceRing )
270 if ( ring.isEmpty() || std::abs( ring.back().x() - curVertex.x() ) > 1 || std::abs( ring.back().y() - curVertex.y() ) > 1 )
272 ring.push_back( curVertex );
274 lastVertex = curVertex;
277 ring.push_back( ring.at( 0 ) );
279 path.addPolygon( ring );
287 QgsMapSettings mapSettings =
mMapCanvas->mapSettings();
300 mRenderContext = createRenderContext();
315 color.setAlpha( alpha );
323 if ( mFeature.hasGeometry() )
325 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayer );
333 if ( layerToCanvasTransform.
isValid() )
343 QgsDebugError( u
"Error transforming canvas extent to layer CRS"_s );
346 if ( !mapExtentInLayerCrs.
isFinite() )
350 context.
setExtent( mapExtentInLayerCrs );
355 QColor tmpColor( 255, 0, 0, 255 );
356 QColor tmpFillColor( 0, 255, 0, 255 );
358 std::unique_ptr<QgsFeatureRenderer> renderer = createRenderer( context, tmpColor, tmpFillColor );
361 QSize imageSize(
mMapCanvas->mapSettings().outputSize() );
362 QImage image = QImage( imageSize.width(), imageSize.height(), QImage::Format_ARGB32 );
364 QPainter imagePainter( &image );
365 imagePainter.setRenderHint( QPainter::Antialiasing,
true );
368 renderer->startRender( context, mFeature.fields() );
370 renderer->renderFeature( mFeature, context );
371 renderer->stopRender( context );
376 int penRed = mPen.color().red();
377 int penGreen = mPen.color().green();
378 int penBlue = mPen.color().blue();
380 double k = ( 255. - mBrush.color().alpha() ) / 255.;
381 QRgb *line =
nullptr;
382 const int height = image.height();
383 const int width = image.width();
384 for (
int r = 0; r < height; r++ )
386 line =
reinterpret_cast<QRgb *
>( image.scanLine( r ) );
389 int alpha = qAlpha( line[
c] );
392 int green = qGreen( line[
c] );
393 line[
c] = qRgba( penRed, penGreen, penBlue, std::clamp(
static_cast<int>( alpha - ( green * k ) ), 30, 255 ) );
398 p->drawImage( 0, 0, image );
401 else if ( !mGeometry.isNull() )
404 p->setBrush( mBrush );
406 switch ( mGeometry.type() )
413 double pointSizeRadius = mPointSizeRadiusMM;
415 PointSymbol symbol = mPointSymbol;
422 pointSizeRadius = 1.2 * 0.5 * mRenderContext.convertToPainterUnits( pcRenderer->pointSize(), pcRenderer->pointSizeUnit(), pcRenderer->pointSizeMapUnitScale() );
424 switch ( pcRenderer->pointSymbol() )
436 for (
auto it = mGeometry.const_parts_begin(); it != mGeometry.const_parts_end(); ++it )
445 if ( !mGeometry.isMultipart() )
447 paintLine( p, mGeometry.asPolyline() );
453 for (
int i = 0; i < m.size(); i++ )
455 paintLine( p, m[i] );
463 if ( !mGeometry.isMultipart() )
465 paintPolygon( p, mGeometry.asPolygon() );
470 for (
int i = 0; i < m.size(); i++ )
472 paintPolygon( p, m[i] );
487 if ( qobject_cast<QgsPointCloudLayer *>( mLayer ) || mFeature.hasGeometry() )
499 QSizeF imageSize =
mMapCanvas->mapSettings().outputSize();
500 QgsRectangle rect( topLeft.
x(), topLeft.
y(), topLeft.
x() + imageSize.width() * res, topLeft.
y() - imageSize.height() * res );
505 else if ( !mGeometry.isNull() )
511 double d =
mMapCanvas->extent().width() * 0.005;
@ Circle
Renders points as circles.
@ Square
Renders points as squares.
static const double DEFAULT_HIGHLIGHT_MIN_WIDTH_MM
Default highlight line/stroke minimum width in mm.
static const double DEFAULT_HIGHLIGHT_BUFFER_MM
Default highlight buffer in mm.
static const QColor DEFAULT_HIGHLIGHT_COLOR
Default highlight color.
RenderUnit
Rendering size units.
@ Millimeters
Millimeters.
@ Reverse
Reverse/inverse transform (from destination to source).
Custom exception class for Coordinate Reference System related exceptions.
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.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
A geometry is the spatial representation of a feature.
void updatePosition() override
called on changed extent or resize event to update position of the item
QgsMapLayer * layer() const
Returns the layer for which this highlight has been created.
QgsHighlight(QgsMapCanvas *mapCanvas, const QgsGeometry &geom, QgsMapLayer *layer)
Constructor for QgsHighlight.
void setBuffer(double buffer)
Sets the line/stroke buffer size (in millimeters).
void setMinWidth(double width)
Sets the minimum line/stroke width (in millimeters).
void setFillColor(const QColor &fillColor)
Fill color for the highlight.
void applyDefaultStyle()
Applies the default style from the user settings to the highlight.
void setWidth(int width)
Set stroke width.
void paint(QPainter *p) override
function to be implemented by derived classes
void updateRect()
recalculates needed rectangle
void setColor(const QColor &color)
Set line/stroke to color, polygon fill to color with alpha = 63.
virtual void setWidth(double width)
Sets the width of the line symbol layer.
virtual double width() const
Returns the estimated width for the line symbol layer.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
QgsRectangle rect() const
returns canvas item rectangle in map units
QPointF toCanvasCoordinates(const QgsPointXY &point) const
transformation from map coordinates to screen coordinates
QgsMapCanvas * mMapCanvas
pointer to map canvas
void setRect(const QgsRectangle &r, bool resetRotation=true)
sets canvas item rectangle in map units
QgsMapCanvasItem(QgsMapCanvas *mapCanvas)
protected constructor: cannot be constructed directly
bool setRenderContextVariables(QPainter *p, QgsRenderContext &context) const
Sets render context parameters.
Map canvas is a class for displaying all GIS data types on a canvas.
void destinationCrsChanged()
Emitted when map CRS has changed.
Base class for all map layer types.
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
Represents a map layer supporting display of point clouds.
Abstract base class for 2d point cloud renderers.
Point geometry type, with support for z-dimension and m-values.
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.
bool isFinite() const
Returns true if the rectangle has finite boundaries.
Contains information about the context of a rendering operation.
void setCoordinateTransform(const QgsCoordinateTransform &t)
Sets the current coordinate transform for the context.
double convertFromPainterUnits(double size, Qgis::RenderUnit unit) const
Converts a size from painter units (pixels) to the specified render unit.
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.
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
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
double strokeWidth() const
void setStrokeWidth(double strokeWidth)
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void setStrokeWidth(double w)
Sets the width of the marker's stroke.
Qgis::RenderUnit strokeWidthUnit() const
Returns the unit for the width of the marker's stroke.
double strokeWidth() const
Returns the width of the marker's stroke.
virtual void setStrokeColor(const QColor &color)
Sets the stroke color for the symbol layer.
@ StrokeColor
Stroke color.
virtual void setFillColor(const QColor &color)
Sets the fill color for the symbol layer.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Represents a vector layer which manages a vector based dataset.
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
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugError(str)
QList< QgsSymbol * > QgsSymbolList