QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsmarkersymbol.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmarkersymbol.cpp
3 ---------------------
4 begin : November 2009
5 copyright : (C) 2009 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
16#include "qgsmarkersymbol.h"
19#include "qgssymbollayerutils.h"
20#include "qgspainteffect.h"
22#include "qgspainting.h"
23#include "qgsfillsymbol.h"
24
25QgsMarkerSymbol *QgsMarkerSymbol::createSimple( const QVariantMap &properties )
26{
28 if ( !sl )
29 return nullptr;
30
31 QgsSymbolLayerList layers;
32 layers.append( sl );
33 return new QgsMarkerSymbol( layers );
34}
35
37 : QgsSymbol( Qgis::SymbolType::Marker, layers )
38{
39 if ( mLayers.isEmpty() )
40 mLayers.append( new QgsSimpleMarkerSymbolLayer() );
41}
42
43void QgsMarkerSymbol::setAngle( double symbolAngle ) const
44{
45 double origAngle = angle();
46 double angleDiff = symbolAngle - origAngle;
47 const auto constMLayers = mLayers;
48 for ( QgsSymbolLayer *layer : constMLayers )
49 {
50 QgsMarkerSymbolLayer *markerLayer = dynamic_cast<QgsMarkerSymbolLayer *>( layer );
51 if ( markerLayer )
52 markerLayer->setAngle( markerLayer->angle() + angleDiff );
53 }
54}
55
57{
58 for ( QgsSymbolLayer *layer : std::as_const( mLayers ) )
59 {
61 continue;
62 const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
63 return markerLayer->angle();
64 }
65 return 0;
66}
67
68void QgsMarkerSymbol::setLineAngle( double lineAng ) const
69{
70 const auto constMLayers = mLayers;
71 for ( QgsSymbolLayer *layer : constMLayers )
72 {
74 continue;
75 QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
76 markerLayer->setLineAngle( lineAng );
77 }
78}
79
81{
82 const double symbolRotation = angle();
83
84
85 for ( QgsSymbolLayer *layer : std::as_const( mLayers ) )
86 {
88 continue;
89 const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
90 if ( !property )
91 {
92 layer->setDataDefinedProperty( QgsSymbolLayer::Property::Angle, QgsProperty() );
93 }
94 else
95 {
96 if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
97 {
98 layer->setDataDefinedProperty( QgsSymbolLayer::Property::Angle, property );
99 }
100 else
101 {
102 QgsProperty rotatedDD = QgsSymbolLayerUtils::rotateWholeSymbol( markerLayer->angle() - symbolRotation, property );
103 layer->setDataDefinedProperty( QgsSymbolLayer::Property::Angle, rotatedDD );
104 }
105 }
106 }
107}
108
110{
111 const double symbolRotation = angle();
112 QgsProperty symbolDD;
113
114 // find the base of the "en masse" pattern
115 const auto layers = mLayers;
116 for ( QgsSymbolLayer *layer : layers )
117 {
119 continue;
120 const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
121 if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) && markerLayer->dataDefinedProperties().isActive( QgsSymbolLayer::Property::Angle ) )
122 {
124 break;
125 }
126 }
127
128 if ( !symbolDD )
129 return QgsProperty();
130
131 // check that all layer's angle expressions match the "en masse" pattern
132 for ( QgsSymbolLayer *layer : layers )
133 {
135 continue;
136 const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
137
139
140 if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
141 {
142 if ( !layerAngleDD || layerAngleDD != symbolDD )
143 return QgsProperty();
144 }
145 else
146 {
147 QgsProperty rotatedDD( QgsSymbolLayerUtils::rotateWholeSymbol( markerLayer->angle() - symbolRotation, symbolDD ) );
148 if ( !layerAngleDD || layerAngleDD != rotatedDD )
149 return QgsProperty();
150 }
151 }
152 return symbolDD;
153}
154
155
156void QgsMarkerSymbol::setSize( double s ) const
157{
158 double origSize = size();
159
160 const auto constMLayers = mLayers;
161 for ( QgsSymbolLayer *layer : constMLayers )
162 {
163 QgsMarkerSymbolLayer *markerLayer = dynamic_cast<QgsMarkerSymbolLayer *>( layer );
164 if ( markerLayer )
165 {
166 if ( qgsDoubleNear( markerLayer->size(), origSize ) )
167 {
168 markerLayer->setSize( s );
169 }
170 else if ( !qgsDoubleNear( origSize, 0.0 ) )
171 {
172 // proportionally scale size
173 markerLayer->setSize( markerLayer->size() * s / origSize );
174 }
175 // also scale offset to maintain relative position
176 if ( !qgsDoubleNear( origSize, 0.0 ) && ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) ) )
177 markerLayer->setOffset( QPointF( markerLayer->offset().x() * s / origSize,
178 markerLayer->offset().y() * s / origSize ) );
179 }
180 else
181 {
182 QgsGeometryGeneratorSymbolLayer *geomGeneratorLayer = dynamic_cast<QgsGeometryGeneratorSymbolLayer *>( layer );
183 if ( geomGeneratorLayer && geomGeneratorLayer->symbolType() == Qgis::SymbolType::Marker )
184 {
185 QgsMarkerSymbol *markerSymbol = qgis::down_cast<QgsMarkerSymbol *>( geomGeneratorLayer->subSymbol() );
186 if ( qgsDoubleNear( markerSymbol->size(), origSize ) )
187 {
188 markerSymbol->setSize( s );
189 }
190 else if ( !qgsDoubleNear( origSize, 0.0 ) )
191 {
192 // proportionally scale the width
193 markerSymbol->setSize( markerSymbol->size() * s / origSize );
194 }
195 }
196 }
197 }
198}
199
201{
202 // return size of the largest symbol
203 double maxSize = 0;
204 const auto constMLayers = mLayers;
205 for ( QgsSymbolLayer *layer : constMLayers )
206 {
207 const QgsMarkerSymbolLayer *markerLayer = dynamic_cast<QgsMarkerSymbolLayer *>( layer );
208 if ( markerLayer )
209 {
210 const double lsize = markerLayer->size();
211 if ( lsize > maxSize )
212 maxSize = lsize;
213 }
214 else
215 {
216 QgsGeometryGeneratorSymbolLayer *geomGeneratorLayer = dynamic_cast<QgsGeometryGeneratorSymbolLayer *>( layer );
217 if ( geomGeneratorLayer && geomGeneratorLayer->symbolType() == Qgis::SymbolType::Marker )
218 {
219 QgsMarkerSymbol *markerSymbol = qgis::down_cast<QgsMarkerSymbol *>( geomGeneratorLayer->subSymbol() );
220 const double lsize = markerSymbol->size();
221 if ( lsize > maxSize )
222 maxSize = lsize;
223 }
224 }
225 }
226 return maxSize;
227}
228
229double QgsMarkerSymbol::size( const QgsRenderContext &context ) const
230{
231 // return size of the largest symbol
232 double maxSize = 0;
233 for ( QgsSymbolLayer *layer : mLayers )
234 {
236 continue;
237 const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
238 const double layerSize = context.convertToPainterUnits( markerLayer->size(), markerLayer->sizeUnit(), markerLayer->sizeMapUnitScale() );
239 maxSize = std::max( maxSize, layerSize );
240 }
241 return maxSize;
242}
243
245{
246 const auto constMLayers = mLayers;
247 for ( QgsSymbolLayer *layer : constMLayers )
248 {
250 continue;
251
252 QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
253 markerLayer->setSizeUnit( unit );
254 }
255}
256
258{
259 bool first = true;
261
262 const auto constMLayers = mLayers;
263 for ( QgsSymbolLayer *layer : constMLayers )
264 {
266 continue;
267 const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
268
269 if ( first )
270 unit = markerLayer->sizeUnit();
271 else
272 {
273 if ( unit != markerLayer->sizeUnit() )
275 }
276
277 first = false;
278 }
279 return unit;
280}
281
283{
284 const auto constMLayers = mLayers;
285 for ( QgsSymbolLayer *layer : constMLayers )
286 {
288 continue;
289
290 QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
291 markerLayer->setSizeMapUnitScale( scale );
292 }
293}
294
296{
297 const auto constMLayers = mLayers;
298 for ( QgsSymbolLayer *layer : constMLayers )
299 {
301 continue;
302
303 QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
304 return markerLayer->sizeMapUnitScale();
305 }
306 return QgsMapUnitScale();
307}
308
310{
311 const double symbolSize = size();
312
313 const auto constMLayers = mLayers;
314 for ( QgsSymbolLayer *layer : constMLayers )
315 {
317 continue;
318 QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
319
320 if ( !property )
321 {
324 }
325 else
326 {
327 if ( qgsDoubleNear( symbolSize, 0.0 ) || qgsDoubleNear( markerLayer->size(), symbolSize ) )
328 {
330 }
331 else
332 {
333 markerLayer->setDataDefinedProperty( QgsSymbolLayer::Property::Size, QgsSymbolLayerUtils::scaleWholeSymbol( markerLayer->size() / symbolSize, property ) );
334 }
335
336 if ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) )
337 {
338 markerLayer->setDataDefinedProperty( QgsSymbolLayer::Property::Offset, QgsSymbolLayerUtils::scaleWholeSymbol(
339 markerLayer->offset().x() / symbolSize,
340 markerLayer->offset().y() / symbolSize, property ) );
341 }
342 }
343 }
344}
345
347{
348 const double symbolSize = size();
349
350 QgsProperty symbolDD;
351
352 // find the base of the "en masse" pattern
353 const auto layers = mLayers;
354 for ( QgsSymbolLayer *layer : layers )
355 {
357 continue;
358 const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
359 if ( qgsDoubleNear( markerLayer->size(), symbolSize ) && markerLayer->dataDefinedProperties().isActive( QgsSymbolLayer::Property::Size ) )
360 {
362 break;
363 }
364 }
365
366 if ( !symbolDD )
367 return QgsProperty();
368
369 // check that all layers size expressions match the "en masse" pattern
370 for ( QgsSymbolLayer *layer : layers )
371 {
373 continue;
374 const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
375
378
379 if ( qgsDoubleNear( markerLayer->size(), symbolSize ) )
380 {
381 if ( !layerSizeDD || layerSizeDD != symbolDD )
382 return QgsProperty();
383 }
384 else
385 {
386 if ( qgsDoubleNear( symbolSize, 0.0 ) )
387 return QgsProperty();
388
389 QgsProperty scaledDD( QgsSymbolLayerUtils::scaleWholeSymbol( markerLayer->size() / symbolSize, symbolDD ) );
390 if ( !layerSizeDD || layerSizeDD != scaledDD )
391 return QgsProperty();
392 }
393
394 QgsProperty scaledOffsetDD( QgsSymbolLayerUtils::scaleWholeSymbol( markerLayer->offset().x() / symbolSize, markerLayer->offset().y() / symbolSize, symbolDD ) );
395 if ( layerOffsetDD && layerOffsetDD != scaledOffsetDD )
396 return QgsProperty();
397 }
398
399 return symbolDD;
400}
401
403{
404 const auto constMLayers = mLayers;
405 for ( QgsSymbolLayer *layer : constMLayers )
406 {
408 continue;
409 QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
410 markerLayer->setScaleMethod( scaleMethod );
411 }
412}
413
415{
416 const auto constMLayers = mLayers;
417 for ( QgsSymbolLayer *layer : constMLayers )
418 {
420 continue;
421 const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
422 // return scale method of the first symbol layer
423 return markerLayer->scaleMethod();
424 }
425
427}
428
429void QgsMarkerSymbol::renderPointUsingLayer( QgsMarkerSymbolLayer *layer, QPointF point, QgsSymbolRenderContext &context )
430{
431 static QPointF nullPoint( 0, 0 );
432
433 if ( layer->dataDefinedProperties().hasActiveProperties() && !layer->dataDefinedProperties().valueAsBool( QgsSymbolLayer::Property::LayerEnabled, context.renderContext().expressionContext(), true ) )
434 return;
435
436 QgsPaintEffect *effect = layer->paintEffect();
437 if ( effect && effect->enabled() )
438 {
439 QgsEffectPainter p( context.renderContext() );
440 p->translate( point );
441 p.setEffect( effect );
442 layer->renderPoint( nullPoint, context );
443 }
444 else
445 {
446 layer->renderPoint( point, context );
447 }
448}
449
450void QgsMarkerSymbol::renderPoint( QPointF point, const QgsFeature *f, QgsRenderContext &context, int layerIdx, bool selected )
451{
453 : mOpacity;
454
455 QgsSymbolRenderContext symbolContext( context, Qgis::RenderUnit::Unknown, opacity, selected, renderHints(), f );
456 symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
457 symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
458
459 // If we're drawing using symbol levels, we only draw buffers for the bottom most level
460 const bool usingBuffer = ( layerIdx == -1 || layerIdx == 0 ) && mBufferSettings && mBufferSettings->enabled() && mBufferSettings->fillSymbol()
462
463 if ( layerIdx != -1 && !usingBuffer )
464 {
465 QgsSymbolLayer *symbolLayer = mLayers.value( layerIdx );
467 {
469 {
470 QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( symbolLayer );
471 renderPointUsingLayer( markerLayer, point, symbolContext );
472 }
473 else
474 {
475 QPolygonF points;
476 points.append( point );
477 renderUsingLayer( symbolLayer, symbolContext, Qgis::GeometryType::Point, &points );
478 }
479 }
480 return;
481 }
482
483 // handle symbol buffers -- we do this by deferring the rendering of the symbol and redirecting
484 // to QPictures, and then using the actual rendered shape from the QPictures to determine the buffer shape.
485 QPainter *originalTargetPainter = nullptr;
486 // this is an array, we need to separate out the symbol layers if we're drawing only one symbol level
487 std::vector< QPicture > picturesForDeferredRendering;
488 std::unique_ptr< QPainter > deferredRenderingPainter;
489 if ( usingBuffer )
490 {
491 originalTargetPainter = context.painter();
492 picturesForDeferredRendering.emplace_back( QPicture() );
493 deferredRenderingPainter = std::make_unique< QPainter >( &picturesForDeferredRendering.front() );
494 context.setPainter( deferredRenderingPainter.get() );
495 }
496
497 int symbolLayerIndex = -1;
498 for ( QgsSymbolLayer *symbolLayer : std::as_const( mLayers ) )
499 {
500 symbolLayerIndex++;
501 if ( context.renderingStopped() )
502 break;
503
504 if ( deferredRenderingPainter && layerIdx != -1 && symbolLayerIndex != 0 )
505 {
506 // if we're using deferred rendering along with symbol level drawing, we
507 // start a new picture for each symbol layer drawn
508 deferredRenderingPainter->end();
509 picturesForDeferredRendering.emplace_back( QPicture() );
510 deferredRenderingPainter->begin( &picturesForDeferredRendering.back() );
511 }
512
513 if ( !symbolLayer->enabled() || !context.isSymbolLayerEnabled( symbolLayer ) )
514 continue;
515
517 {
518 QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( symbolLayer );
519 renderPointUsingLayer( markerLayer, point, symbolContext );
520 }
521 else
522 {
523 QPolygonF points;
524 points.append( point );
525 renderUsingLayer( symbolLayer, symbolContext, Qgis::GeometryType::Point, &points );
526 }
527 }
528
529 // if required, render the calculated buffer below the symbol
530 if ( usingBuffer )
531 {
532 deferredRenderingPainter->end();
533 deferredRenderingPainter.reset();
534
535 QgsGeometryPaintDevice geometryPaintDevice;
536 QPainter geometryPainter( &geometryPaintDevice );
537 // render all the symbol layers onto the geometry painter, so we can calculate a single
538 // buffer for ALL of them
539 for ( const auto &deferredPicture : picturesForDeferredRendering )
540 {
541 QgsPainting::drawPicture( &geometryPainter, QPointF( 0, 0 ), deferredPicture );
542 }
543 geometryPainter.end();
544
545 // retrieve the shape of the rendered symbol
546 const QgsGeometry renderedShape( geometryPaintDevice.geometry().clone() );
547
548 context.setPainter( originalTargetPainter );
549
550 // next, buffer out the rendered shape, and draw!
551 const double bufferSize = context.convertToPainterUnits( mBufferSettings->size(), mBufferSettings->sizeUnit(), mBufferSettings->sizeMapUnitScale() );
553 switch ( mBufferSettings->joinStyle() )
554 {
555 case Qt::MiterJoin:
556 case Qt::SvgMiterJoin:
557 joinStyle = Qgis::JoinStyle::Miter;
558 break;
559 case Qt::BevelJoin:
560 joinStyle = Qgis::JoinStyle::Bevel;
561 break;
562 case Qt::RoundJoin:
563 joinStyle = Qgis::JoinStyle::Round;
564 break;
565
566 case Qt::MPenJoinStyle:
567 break;
568 }
569
570 const QgsGeometry bufferedGeometry = renderedShape.buffer( bufferSize, 8, Qgis::EndCapStyle::Round, joinStyle, 2 );
571 const QList<QList<QPolygonF> > polygons = QgsSymbolLayerUtils::toQPolygonF( bufferedGeometry, Qgis::SymbolType::Fill );
572 for ( const QList< QPolygonF > &polygon : polygons )
573 {
574 QVector< QPolygonF > rings;
575 for ( int i = 1; i < polygon.size(); ++i )
576 rings << polygon.at( i );
577 mBufferSettings->fillSymbol()->renderPolygon( polygon.value( 0 ), &rings, nullptr, context );
578 }
579
580 // finally, draw the actual rendered symbol on top. If symbol levels are at play then this will ONLY
581 // be the target symbol level, not all of them.
582 QgsPainting::drawPicture( context.painter(), QPointF( 0, 0 ), picturesForDeferredRendering.front() );
583 }
584}
585
586QRectF QgsMarkerSymbol::bounds( QPointF point, QgsRenderContext &context, const QgsFeature &feature ) const
587{
588 QgsSymbolRenderContext symbolContext( context, Qgis::RenderUnit::Unknown, mOpacity, false, renderHints(), &feature, feature.fields() );
589
590 QRectF bound;
591 const auto constMLayers = mLayers;
592 for ( QgsSymbolLayer *layer : constMLayers )
593 {
595 {
596 if ( !layer->enabled()
597 || ( layer->dataDefinedProperties().hasActiveProperties() && !layer->dataDefinedProperties().valueAsBool( QgsSymbolLayer::Property::LayerEnabled, context.expressionContext(), true ) ) )
598 continue;
599
601 if ( bound.isNull() )
602 bound = symbolLayer->bounds( point, symbolContext );
603 else
604 bound = bound.united( symbolLayer->bounds( point, symbolContext ) );
605 }
606 }
607 return bound;
608}
609
611{
612 QgsMarkerSymbol *cloneSymbol = new QgsMarkerSymbol( cloneLayers() );
613 cloneSymbol->copyCommonProperties( this );
614 return cloneSymbol;
615}
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
@ ExcludeSymbolBuffers
Do not render symbol buffers.
ScaleMethod
Scale methods.
Definition qgis.h:588
JoinStyle
Join styles for buffers.
Definition qgis.h:2031
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RenderUnit
Rendering size units.
Definition qgis.h:4910
@ Unknown
Mixed or unknown units.
@ Round
Round cap.
@ Marker
Marker symbol.
@ Fill
Fill symbol.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
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.
A class to manager painter saving and restoring required for effect drawing.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsFields fields
Definition qgsfeature.h:68
A symbol layer subclass which alters rendered feature shapes through the use of QGIS expressions.
Qgis::SymbolType symbolType() const
Access the symbol type.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
A paint device which converts everything renderer to a QgsGeometry representation of the rendered sha...
const QgsAbstractGeometry & geometry() const
Returns the rendered geometry.
A geometry is the spatial representation of a feature.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
Qgis::LayerType type
Definition qgsmaplayer.h:86
Struct for storing maximum and minimum scales for measurements in map units.
Abstract base class for marker symbol layers.
virtual void setSize(double size)
Sets the symbol size.
QPointF offset() const
Returns the marker's offset, which is the horizontal and vertical displacement which the rendered mar...
void setAngle(double angle)
Sets the rotation angle for the marker.
Qgis::ScaleMethod scaleMethod() const
Returns the method to use for scaling the marker's size.
const QgsMapUnitScale & sizeMapUnitScale() const
Returns the map unit scale for the symbol's size.
void setOffset(QPointF offset)
Sets the marker's offset, which is the horizontal and vertical displacement which the rendered marker...
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol's size.
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol's angle.
double size() const
Returns the symbol size.
void setScaleMethod(Qgis::ScaleMethod scaleMethod)
Sets the method to use for scaling the marker's size.
Qgis::RenderUnit sizeUnit() const
Returns the units for the symbol's size.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units for the symbol's size.
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
A marker symbol type, for rendering Point and MultiPoint geometries.
void setScaleMethod(Qgis::ScaleMethod scaleMethod) const
Sets the method to use for scaling the marker's size.
void setAngle(double symbolAngle) const
Sets the angle for the whole symbol.
void setSize(double size) const
Sets the size for the whole symbol.
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
QgsProperty dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
QgsMarkerSymbol(const QgsSymbolLayerList &layers=QgsSymbolLayerList())
Constructor for QgsMarkerSymbol, with the specified list of initial symbol layers.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
double angle() const
Returns the marker angle for the whole symbol.
QgsMapUnitScale sizeMapUnitScale() const
Returns the size map unit scale for the whole symbol.
void setLineAngle(double lineAngle) const
Sets the line angle modification for the symbol's angle.
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
void setDataDefinedSize(const QgsProperty &property) const
Set data defined size for whole symbol (including all symbol layers).
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
void setSizeMapUnitScale(const QgsMapUnitScale &scale) const
Sets the size map unit scale for the whole symbol (including all symbol layers).
Qgis::ScaleMethod scaleMethod() const
Returns the method to use for scaling the marker's size.
void renderPoint(QPointF point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol at the specified point, using the given render context.
Qgis::RenderUnit sizeUnit() const
Returns the size units for the whole symbol (including all symbol layers).
void setDataDefinedAngle(const QgsProperty &property)
Set data defined angle for whole symbol (including all symbol layers).
QRectF bounds(QPointF point, QgsRenderContext &context, const QgsFeature &feature=QgsFeature()) const
Returns the approximate bounding box of the marker symbol, which includes the bounding box of all sym...
void setSizeUnit(Qgis::RenderUnit unit) const
Sets the size units for the whole symbol (including all symbol layers).
Base class for visual effects which can be applied to QPicture drawings.
bool enabled() const
Returns whether the effect is enabled.
static void drawPicture(QPainter *painter, const QPointF &point, const QPicture &picture)
Draws a picture onto a painter, correctly applying workarounds to avoid issues with incorrect scaling...
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
bool hasActiveProperties() const final
Returns true if the collection has any active properties, or false if all properties within the colle...
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
A store for object properties.
Contains information about the context of a rendering operation.
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 setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
bool isSymbolLayerEnabled(const QgsSymbolLayer *layer) const
When rendering a map layer in a second pass (for selective masking), some symbol layers may be disabl...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleMarkerSymbolLayer.
static QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
Qgis::SymbolType type() const
@ Offset
Symbol offset.
@ LayerEnabled
Whether symbol layer is enabled.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
Qgis::SymbolRenderHints renderHints() const
Returns the rendering hint flags for the symbol.
void setGeometryPartCount(int count)
Sets the part count of current geometry.
void setGeometryPartNum(int num)
Sets the part number of current geometry.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
void renderUsingLayer(QgsSymbolLayer *layer, QgsSymbolRenderContext &context, Qgis::GeometryType geometryType=Qgis::GeometryType::Unknown, const QPolygonF *points=nullptr, const QVector< QPolygonF > *rings=nullptr)
Renders a context using a particular symbol layer without passing in a geometry.
QgsSymbolLayerList cloneLayers() const
Retrieve a cloned list of all layers that make up this symbol.
QgsSymbolRenderContext * symbolRenderContext()
Returns the symbol render context.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Qgis::SymbolRenderHints renderHints() const
Returns the rendering hint flags for the symbol.
void copyCommonProperties(const QgsSymbol *other)
Copies common properties from an other symbol to this symbol.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
Definition qgssymbol.h:788
qreal mOpacity
Symbol opacity (in the range 0 - 1)
Definition qgssymbol.h:1000
qreal opacity() const
Returns the opacity for the symbol.
Definition qgssymbol.h:633
std::unique_ptr< QgsSymbolBufferSettings > mBufferSettings
Definition qgssymbol.h:1014
QgsSymbolLayerList mLayers
Definition qgssymbol.h:994
Q_DECL_DEPRECATED const QgsVectorLayer * layer() const
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:6066
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition qgssymbol.h:30
#define DEFAULT_SCALE_METHOD