QGIS API Documentation 3.99.0-Master (e9821da5c6b)
Loading...
Searching...
No Matches
qgsellipsesymbollayer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsellipsesymbollayer.cpp
3 ---------------------
4 begin : June 2011
5 copyright : (C) 2011 by Marco Hugentobler
6 email : marco dot hugentobler at sourcepole dot ch
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 "qgscolorutils.h"
19#include "qgsdxfexport.h"
20#include "qgsfeature.h"
21#include "qgslogger.h"
22#include "qgsproperty.h"
23#include "qgsrendercontext.h"
24#include "qgssldexportcontext.h"
25#include "qgssymbollayerutils.h"
26#include "qgsunittypes.h"
27
28#include <QDomDocument>
29#include <QDomElement>
30#include <QPainter>
31#include <QSet>
32#include <QString>
33
34using namespace Qt::StringLiterals;
35
37 : mStrokeColor( QColor( 35, 35, 35 ) )
38{
39 mColor = Qt::white;
40 mPen.setColor( mStrokeColor );
41 mPen.setStyle( mStrokeStyle );
42 mPen.setJoinStyle( mPenJoinStyle );
43 mPen.setWidth( 1.0 );
44 mBrush.setColor( mColor );
45 mBrush.setStyle( Qt::SolidPattern );
46 mOffset = QPointF( 0, 0 );
47 mAngle = 0;
48}
49
51
53{
55 if ( properties.contains( u"symbol_name"_s ) )
56 {
57 layer->setShape( decodeShape( properties[ u"symbol_name"_s].toString() ) );
58 }
59 if ( properties.contains( u"size"_s ) )
60 {
61 layer->setSize( properties[u"size"_s].toDouble() );
62 }
63 if ( properties.contains( u"size_unit"_s ) )
64 {
65 layer->setSizeUnit( QgsUnitTypes::decodeRenderUnit( properties[u"size_unit"_s].toString() ) );
66 }
67 if ( properties.contains( u"size_map_unit_scale"_s ) )
68 {
69 layer->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[u"size_map_unit_scale"_s].toString() ) );
70 }
71 if ( properties.contains( u"symbol_width"_s ) )
72 {
73 layer->setSymbolWidth( properties[u"symbol_width"_s].toDouble() );
74 }
75 if ( properties.contains( u"symbol_width_unit"_s ) )
76 {
77 layer->setSymbolWidthUnit( QgsUnitTypes::decodeRenderUnit( properties[u"symbol_width_unit"_s].toString() ) );
78 }
79 if ( properties.contains( u"symbol_width_map_unit_scale"_s ) )
80 {
81 layer->setSymbolWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[u"symbol_width_map_unit_scale"_s].toString() ) );
82 }
83 if ( properties.contains( u"symbol_height"_s ) )
84 {
85 layer->setSymbolHeight( properties[u"symbol_height"_s].toDouble() );
86 }
87 if ( properties.contains( u"symbol_height_unit"_s ) )
88 {
89 layer->setSymbolHeightUnit( QgsUnitTypes::decodeRenderUnit( properties[u"symbol_height_unit"_s].toString() ) );
90 }
91 if ( properties.contains( u"symbol_height_map_unit_scale"_s ) )
92 {
93 layer->setSymbolHeightMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[u"symbol_height_map_unit_scale"_s].toString() ) );
94 }
95 if ( properties.contains( u"angle"_s ) )
96 {
97 layer->setAngle( properties[u"angle"_s].toDouble() );
98 }
99 if ( properties.contains( u"outline_style"_s ) )
100 {
101 layer->setStrokeStyle( QgsSymbolLayerUtils::decodePenStyle( properties[u"outline_style"_s].toString() ) );
102 }
103 else if ( properties.contains( u"line_style"_s ) )
104 {
105 layer->setStrokeStyle( QgsSymbolLayerUtils::decodePenStyle( properties[u"line_style"_s].toString() ) );
106 }
107 if ( properties.contains( u"joinstyle"_s ) )
108 {
109 layer->setPenJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( properties[u"joinstyle"_s].toString() ) );
110 }
111 if ( properties.contains( u"cap_style"_s ) )
112 {
113 layer->setPenCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( properties[u"cap_style"_s].toString() ) );
114 }
115 if ( properties.contains( u"outline_width"_s ) )
116 {
117 layer->setStrokeWidth( properties[u"outline_width"_s].toDouble() );
118 }
119 else if ( properties.contains( u"line_width"_s ) )
120 {
121 layer->setStrokeWidth( properties[u"line_width"_s].toDouble() );
122 }
123 if ( properties.contains( u"outline_width_unit"_s ) )
124 {
125 layer->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( properties[u"outline_width_unit"_s].toString() ) );
126 }
127 else if ( properties.contains( u"line_width_unit"_s ) )
128 {
129 layer->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( properties[u"line_width_unit"_s].toString() ) );
130 }
131 if ( properties.contains( u"outline_width_map_unit_scale"_s ) )
132 {
133 layer->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[u"outline_width_map_unit_scale"_s].toString() ) );
134 }
135 if ( properties.contains( u"fill_color"_s ) )
136 {
137 //pre 2.5 projects used "fill_color"
138 layer->setFillColor( QgsColorUtils::colorFromString( properties[u"fill_color"_s].toString() ) );
139 }
140 else if ( properties.contains( u"color"_s ) )
141 {
142 layer->setFillColor( QgsColorUtils::colorFromString( properties[u"color"_s].toString() ) );
143 }
144 if ( properties.contains( u"outline_color"_s ) )
145 {
146 layer->setStrokeColor( QgsColorUtils::colorFromString( properties[u"outline_color"_s].toString() ) );
147 }
148 else if ( properties.contains( u"line_color"_s ) )
149 {
150 layer->setStrokeColor( QgsColorUtils::colorFromString( properties[u"line_color"_s].toString() ) );
151 }
152 if ( properties.contains( u"offset"_s ) )
153 {
154 layer->setOffset( QgsSymbolLayerUtils::decodePoint( properties[u"offset"_s].toString() ) );
155 }
156 if ( properties.contains( u"offset_unit"_s ) )
157 {
158 layer->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( properties[u"offset_unit"_s].toString() ) );
159 }
160 if ( properties.contains( u"offset_map_unit_scale"_s ) )
161 {
162 layer->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[u"offset_map_unit_scale"_s].toString() ) );
163 }
164 if ( properties.contains( u"horizontal_anchor_point"_s ) )
165 {
166 layer->setHorizontalAnchorPoint( static_cast< Qgis::HorizontalAnchorPoint >( properties[ u"horizontal_anchor_point"_s].toInt() ) );
167 }
168 if ( properties.contains( u"vertical_anchor_point"_s ) )
169 {
170 layer->setVerticalAnchorPoint( static_cast< Qgis::VerticalAnchorPoint >( properties[ u"vertical_anchor_point"_s].toInt() ) );
171 }
172
173 //data defined properties
175
176 return layer;
177}
178
180{
181 double scaledWidth = mSymbolWidth;
182 double scaledHeight = mSymbolHeight;
183
184 QColor brushColor = mColor;
185 brushColor.setAlphaF( brushColor.alphaF() * context.opacity() );
186 mBrush.setColor( brushColor );
187
188 QColor penColor = mStrokeColor;
189 penColor.setAlphaF( penColor.alphaF() * context.opacity() );
190 mPen.setColor( penColor );
191
192 bool ok;
194 {
195 context.setOriginalValueVariable( mStrokeWidth );
197 if ( !QgsVariantUtils::isNull( exprVal ) )
198 {
199 double width = exprVal.toDouble( &ok );
200 if ( ok )
201 {
202 width = context.renderContext().convertToPainterUnits( width, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
203 mPen.setWidthF( width );
204 mSelPen.setWidthF( width );
205 }
206 }
207 }
208
210 {
213 if ( !QgsVariantUtils::isNull( exprVal ) )
214 {
215 mPen.setStyle( QgsSymbolLayerUtils::decodePenStyle( exprVal.toString() ) );
216 mSelPen.setStyle( mPen.style() );
217 }
218 }
219
221 {
224 if ( !QgsVariantUtils::isNull( exprVal ) )
225 {
226 mPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( exprVal.toString() ) );
227 mSelPen.setJoinStyle( mPen.joinStyle() );
228 }
229 }
230
232 {
234 const QString style = mDataDefinedProperties.valueAsString( QgsSymbolLayer::Property::CapStyle, context.renderContext().expressionContext(), QString(), &ok );
235 if ( ok )
236 {
237 mPen.setCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( style ) );
238 mSelPen.setCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( style ) );
239 }
240 }
241
243 {
246 brushColor.setAlphaF( brushColor.alphaF() * context.opacity() );
247 mBrush.setColor( brushColor );
248 }
249
251 {
253 QColor penColor = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::Property::StrokeColor, context.renderContext().expressionContext(), mStrokeColor );
254 penColor.setAlphaF( penColor.alphaF() * context.opacity() );
255 mPen.setColor( penColor );
256 }
257
260 {
262 const QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::Property::Name, context.renderContext().expressionContext() );
263 if ( !QgsVariantUtils::isNull( exprVal ) )
264 {
265 shape = decodeShape( exprVal.toString() );
266 }
267 preparePath( shape, context, &scaledWidth, &scaledHeight, context.feature() );
268 }
269
270 //offset and rotation
271 bool hasDataDefinedRotation = false;
272 QPointF offset;
273 double angle = 0;
274 calculateOffsetAndRotation( context, scaledWidth, scaledHeight, hasDataDefinedRotation, offset, angle );
275
276 QPainter *p = context.renderContext().painter();
277 if ( !p )
278 {
279 return;
280 }
281
282 QTransform transform;
283 transform.translate( point.x() + offset.x(), point.y() + offset.y() );
284 if ( !qgsDoubleNear( angle, 0.0 ) )
285 {
286 transform.rotate( angle );
287 }
288
289 const bool useSelectedColor = shouldRenderUsingSelectionColor( context );
290 if ( shapeIsFilled( shape ) )
291 {
292 p->setPen( useSelectedColor ? mSelPen : mPen );
293 p->setBrush( useSelectedColor ? mSelBrush : mBrush );
294 }
295 else
296 {
297 p->setPen( useSelectedColor ? mSelPen : mPen );
298 p->setBrush( QBrush() );
299 }
300 p->drawPath( transform.map( mPainterPath ) );
301}
302
303
304void QgsEllipseSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context,
305 double scaledWidth,
306 double scaledHeight,
307 bool &hasDataDefinedRotation,
308 QPointF &offset,
309 double &angle ) const
310{
311 double offsetX = 0;
312 double offsetY = 0;
313 markerOffset( context, scaledWidth, scaledHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY, mSymbolWidthMapUnitScale, mSymbolHeightMapUnitScale );
314 offset = QPointF( offsetX, offsetY );
315
316//priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
317 const bool ok = true;
319 bool usingDataDefinedRotation = false;
321 {
324 usingDataDefinedRotation = ok;
325 }
326
327 hasDataDefinedRotation = context.renderHints() & Qgis::SymbolRenderHint::DynamicRotation || usingDataDefinedRotation;
328 if ( hasDataDefinedRotation )
329 {
330 // For non-point markers, "dataDefinedRotation" means following the
331 // shape (shape-data defined). For them, "field-data defined" does
332 // not work at all. TODO: if "field-data defined" ever gets implemented
333 // we'll need a way to distinguish here between the two, possibly
334 // using another flag in renderHints()
335 const QgsFeature *f = context.feature();
336 if ( f )
337 {
338 const QgsGeometry g = f->geometry();
339 if ( !g.isNull() && g.type() == Qgis::GeometryType::Point )
340 {
341 const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
342 angle += m2p.mapRotation();
343 }
344 }
345 }
346
347 if ( angle )
349}
350
352{
353 return u"EllipseMarker"_s;
354}
355
360
362{
363 QgsMarkerSymbolLayer::startRender( context ); // get anchor point expressions
364 if ( !context.feature() || !dataDefinedProperties().hasActiveProperties() )
365 {
366 preparePath( mShape, context );
367 }
368 mPen.setColor( mStrokeColor );
369 mPen.setStyle( mStrokeStyle );
370 mPen.setJoinStyle( mPenJoinStyle );
371 mPen.setCapStyle( mPenCapStyle );
372 mPen.setWidthF( context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale ) );
373 mBrush.setColor( mColor );
374
375 QColor selBrushColor = context.renderContext().selectionColor();
376 QColor selPenColor = selBrushColor == mColor ? selBrushColor : mStrokeColor;
377 if ( context.opacity() < 1 && !SELECTION_IS_OPAQUE )
378 {
379 selBrushColor.setAlphaF( context.opacity() );
380 selPenColor.setAlphaF( context.opacity() );
381 }
382 mSelBrush = QBrush( selBrushColor );
383 mSelPen = QPen( !shapeIsFilled( mShape ) ? selBrushColor : selPenColor );
384 mSelPen.setStyle( mStrokeStyle );
385 mSelPen.setWidthF( context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale ) );
386}
387
391
393{
399 m->setShape( mShape );
400 m->setSymbolWidth( mSymbolWidth );
401 m->setSymbolHeight( mSymbolHeight );
402 m->setStrokeStyle( mStrokeStyle );
403 m->setOffset( mOffset );
404 m->setStrokeStyle( mStrokeStyle );
405 m->setPenJoinStyle( mPenJoinStyle );
406 m->setPenCapStyle( mPenCapStyle );
407 m->setStrokeWidth( mStrokeWidth );
408 m->setColor( color() );
409 m->setStrokeColor( mStrokeColor );
410 m->setSymbolWidthUnit( mSymbolWidthUnit );
411 m->setSymbolWidthMapUnitScale( mSymbolWidthMapUnitScale );
412 m->setSymbolHeightUnit( mSymbolHeightUnit );
413 m->setSymbolHeightMapUnitScale( mSymbolHeightMapUnitScale );
414 m->setStrokeWidthUnit( mStrokeWidthUnit );
415 m->setStrokeWidthMapUnitScale( mStrokeWidthMapUnitScale );
416 m->setAngle( mAngle );
419
421 return m;
422}
423
424void QgsEllipseSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
425{
426 QgsSldExportContext context;
427 context.setExtraProperties( props );
428 toSld( doc, element, context );
429}
430
431bool QgsEllipseSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, QgsSldExportContext &context ) const
432{
433 QDomElement symbolizerElem = doc.createElement( u"se:PointSymbolizer"_s );
434 const QVariantMap props = context.extraProperties();
435 if ( !props.value( u"uom"_s, QString() ).toString().isEmpty() )
436 symbolizerElem.setAttribute( u"uom"_s, props.value( u"uom"_s, QString() ).toString() );
437 element.appendChild( symbolizerElem );
438
439 // <Geometry>
440 QgsSymbolLayerUtils::createGeometryElement( doc, symbolizerElem, props.value( u"geom"_s, QString() ).toString(), context );
441
442 return writeSldMarker( doc, symbolizerElem, context );
443}
444
445void QgsEllipseSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
446{
447 QgsSldExportContext context;
448 context.setExtraProperties( props );
449 writeSldMarker( doc, element, context );
450}
451
452bool QgsEllipseSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, QgsSldExportContext &context ) const
453{
454 // <Graphic>
455 QDomElement graphicElem = doc.createElement( u"se:Graphic"_s );
456 element.appendChild( graphicElem );
457
458 const QVariantMap props = context.extraProperties();
459 const double strokeWidth = QgsSymbolLayerUtils::rescaleUom( mStrokeWidth, mStrokeWidthUnit, props );
460 const double symbolWidth = QgsSymbolLayerUtils::rescaleUom( mSymbolWidth, mSymbolWidthUnit, props );
461 QgsSymbolLayerUtils::wellKnownMarkerToSld( doc, graphicElem, encodeShape( mShape ), mColor, mStrokeColor, mStrokeStyle, context, strokeWidth, symbolWidth );
462
463 // <Rotation>
465
466 QString angleFunc = props.value( u"angle"_s, QString() ).toString();
467 if ( angleFunc.isEmpty() ) // symbol has no angle set
468 {
469 if ( ddRotation && ddRotation.isActive() )
470 {
471 angleFunc = ddRotation.asExpression();
472 }
473 else if ( !qgsDoubleNear( mAngle, 0.0 ) )
474 angleFunc = QString::number( mAngle );
475 }
476 else if ( ddRotation && ddRotation.isActive() )
477 {
478 // the symbol has an angle and the symbol layer have a rotation
479 // property set
480 angleFunc = u"%1 + %2"_s.arg( angleFunc, ddRotation.asExpression() );
481 }
482 else if ( !qgsDoubleNear( mAngle, 0.0 ) )
483 {
484 // both the symbol and the symbol layer have angle value set
485 bool ok;
486 const double angle = angleFunc.toDouble( &ok );
487 if ( !ok )
488 {
489 // its a string (probably a property name or a function)
490 angleFunc = u"%1 + %2"_s.arg( angleFunc ).arg( mAngle );
491 }
492 else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
493 {
494 // it's a double value
495 angleFunc = QString::number( angle + mAngle );
496 }
497 }
498 QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc, context );
499
500 // <Displacement>
503
504 // store w/h factor in a <VendorOption>
505 const double widthHeightFactor = mSymbolWidth / mSymbolHeight;
506 const QDomElement factorElem = QgsSymbolLayerUtils::createVendorOptionElement( doc, u"widthHeightFactor"_s, QString::number( widthHeightFactor ) );
507 graphicElem.appendChild( factorElem );
508 return true;
509}
510
512{
513 QgsDebugMsgLevel( u"Entered."_s, 4 );
514
515 QDomElement graphicElem = element.firstChildElement( u"Graphic"_s );
516 if ( graphicElem.isNull() )
517 return nullptr;
518
519 QString name = u"circle"_s;
520 QColor fillColor, strokeColor;
521 double strokeWidth, size;
522 double widthHeightFactor = 1.0;
523 Qt::PenStyle strokeStyle;
524
525 QgsStringMap vendorOptions = QgsSymbolLayerUtils::getVendorOptionList( graphicElem );
526 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
527 {
528 if ( it.key() == "widthHeightFactor"_L1 )
529 {
530 bool ok;
531 const double v = it.value().toDouble( &ok );
532 if ( ok && !qgsDoubleNear( v, 0.0 ) && v > 0 )
533 widthHeightFactor = v;
534 }
535 }
536
538 return nullptr;
539
540 double scaleFactor = 1.0;
541 const QString uom = element.attribute( u"uom"_s );
542 Qgis::RenderUnit sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( uom, &scaleFactor );
543 size = size * scaleFactor;
544 strokeWidth = strokeWidth * scaleFactor;
545
546 double angle = 0.0;
547 QString angleFunc;
548 if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
549 {
550 bool ok;
551 const double d = angleFunc.toDouble( &ok );
552 if ( ok )
553 angle = d;
554 }
555
557 m->setOutputUnit( sldUnitSize );
558 m->setShape( decodeShape( name ) );
563 m->setSymbolWidth( size );
564 m->setSymbolHeight( size / widthHeightFactor );
565 m->setAngle( angle );
566 return m;
567}
568
570{
571 QVariantMap map;
572 map[u"symbol_name"_s] = encodeShape( mShape );
573 map[u"symbol_width"_s] = QString::number( mSymbolWidth );
574 map[u"symbol_width_unit"_s] = QgsUnitTypes::encodeUnit( mSymbolWidthUnit );
575 map[u"symbol_width_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mSymbolWidthMapUnitScale );
576 map[u"symbol_height"_s] = QString::number( mSymbolHeight );
577 map[u"symbol_height_unit"_s] = QgsUnitTypes::encodeUnit( mSymbolHeightUnit );
578 map[u"symbol_height_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mSymbolHeightMapUnitScale );
579 map[u"angle"_s] = QString::number( mAngle );
580 map[u"outline_style"_s] = QgsSymbolLayerUtils::encodePenStyle( mStrokeStyle );
581 map[u"outline_width"_s] = QString::number( mStrokeWidth );
582 map[u"outline_width_unit"_s] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
583 map[u"outline_width_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
584 map[u"joinstyle"_s] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
585 map[u"cap_style"_s] = QgsSymbolLayerUtils::encodePenCapStyle( mPenCapStyle );
586 map[u"color"_s] = QgsColorUtils::colorToString( mColor );
587 map[u"outline_color"_s] = QgsColorUtils::colorToString( mStrokeColor );
588 map[u"offset"_s] = QgsSymbolLayerUtils::encodePoint( mOffset );
589 map[u"offset_unit"_s] = QgsUnitTypes::encodeUnit( mOffsetUnit );
590 map[u"offset_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
591 map[u"size"_s] = QString::number( mSize );
592 map[u"size_unit"_s] = QgsUnitTypes::encodeUnit( mSizeUnit );
593 map[u"size_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
594 map[u"horizontal_anchor_point"_s] = QString::number( static_cast< int >( mHorizontalAnchorPoint ) );
595 map[u"vertical_anchor_point"_s] = QString::number( static_cast< int >( mVerticalAnchorPoint ) );
596 return map;
597}
598
599QSizeF QgsEllipseSymbolLayer::calculateSize( QgsSymbolRenderContext &context, double *scaledWidth, double *scaledHeight )
600{
601 double width = 0;
602
603 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Width ) ) //1. priority: data defined setting on symbol layer le
604 {
605 context.setOriginalValueVariable( mSymbolWidth );
607 }
608 else //2. priority: global width setting
609 {
610 width = mSymbolWidth;
611 }
612 if ( scaledWidth )
613 {
614 *scaledWidth = width;
615 }
616 width = context.renderContext().convertToPainterUnits( width, mSymbolWidthUnit, mSymbolHeightMapUnitScale );
617
618 double height = 0;
619 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Height ) ) //1. priority: data defined setting on symbol layer level
620 {
621 context.setOriginalValueVariable( mSymbolHeight );
622 height = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::Property::Height, context.renderContext().expressionContext(), mSymbolHeight );
623 }
624 else //2. priority: global height setting
625 {
626 height = mSymbolHeight;
627 }
628 if ( scaledHeight )
629 {
630 *scaledHeight = height;
631 }
632 height = context.renderContext().convertToPainterUnits( height, mSymbolHeightUnit, mSymbolHeightMapUnitScale );
633 return QSizeF( width, height );
634}
635
636void QgsEllipseSymbolLayer::preparePath( const QgsEllipseSymbolLayer::Shape &shape, QgsSymbolRenderContext &context, double *scaledWidth, double *scaledHeight, const QgsFeature * )
637{
638 mPainterPath = QPainterPath();
639
640 const QSizeF size = calculateSize( context, scaledWidth, scaledHeight );
641
642 switch ( shape )
643 {
644 case Circle:
645 mPainterPath.addEllipse( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) );
646 return;
647
648 case SemiCircle:
649 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 0, 180 );
650 mPainterPath.lineTo( 0, 0 );
651 return;
652
653 case ThirdCircle:
654 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 90, 120 );
655 mPainterPath.lineTo( 0, 0 );
656 return;
657
658 case QuarterCircle:
659 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 90, 90 );
660 mPainterPath.lineTo( 0, 0 );
661 return;
662
663 case Rectangle:
664 mPainterPath.addRect( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) );
665 return;
666
667 case Diamond:
668 mPainterPath.moveTo( -size.width() / 2.0, 0 );
669 mPainterPath.lineTo( 0, size.height() / 2.0 );
670 mPainterPath.lineTo( size.width() / 2.0, 0 );
671 mPainterPath.lineTo( 0, -size.height() / 2.0 );
672 mPainterPath.lineTo( -size.width() / 2.0, 0 );
673 return;
674
675 case Cross:
676 mPainterPath.moveTo( 0, -size.height() / 2.0 );
677 mPainterPath.lineTo( 0, size.height() / 2.0 );
678 mPainterPath.moveTo( -size.width() / 2.0, 0 );
679 mPainterPath.lineTo( size.width() / 2.0, 0 );
680 return;
681
682 case Arrow:
683 mPainterPath.moveTo( -size.width() / 2.0, size.height() / 2.0 );
684 mPainterPath.lineTo( 0, -size.height() / 2.0 );
685 mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
686 return;
687
688 case HalfArc:
689 mPainterPath.moveTo( size.width() / 2.0, 0 );
690 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 0, 180 );
691 return;
692
693 case Triangle:
694 mPainterPath.moveTo( 0, -size.height() / 2.0 );
695 mPainterPath.lineTo( -size.width() / 2.0, size.height() / 2.0 );
696 mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
697 mPainterPath.lineTo( 0, -size.height() / 2.0 );
698 return;
699
700 case LeftHalfTriangle:
701 mPainterPath.moveTo( 0, size.height() / 2.0 );
702 mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
703 mPainterPath.lineTo( 0, -size.height() / 2.0 );
704 mPainterPath.lineTo( 0, size.height() / 2.0 );
705 return;
706
708 mPainterPath.moveTo( -size.width() / 2.0, size.height() / 2.0 );
709 mPainterPath.lineTo( 0, size.height() / 2.0 );
710 mPainterPath.lineTo( 0, -size.height() / 2.0 );
711 mPainterPath.lineTo( -size.width() / 2.0, size.height() / 2.0 );
712 return;
713
714 case Pentagon:
715 mPainterPath.moveTo( ( size.width() * -0.9511 ) / 2.0, size.height() / ( 2 / -0.309 ) );
716 mPainterPath.lineTo( ( size.width() * -0.5878 ) / 2.0, size.height() / ( 2 / 0.8090 ) );
717 mPainterPath.lineTo( ( size.width() * 0.5878 ) / 2.0, size.height() / ( 2 / 0.8090 ) );
718 mPainterPath.lineTo( ( size.width() * 0.9511 ) / 2.0, size.height() / ( 2 / -0.309 ) );
719 mPainterPath.lineTo( 0, size.height() / -2.0 );
720 mPainterPath.lineTo( ( size.width() * -0.9511 ) / 2.0, size.height() / ( 2 / -0.309 ) );
721 return;
722
723 case Hexagon:
724 mPainterPath.moveTo( ( size.width() * 0.8660 ) / 2.0, size.height() / 4.0 );
725 mPainterPath.lineTo( ( size.width() * 0.8660 ) / 2.0, size.height() / -4.0 );
726 mPainterPath.lineTo( 0, size.height() / -2.0 );
727 mPainterPath.lineTo( ( size.width() * 0.8660 ) / -2.0, size.height() / -4.0 );
728 mPainterPath.lineTo( ( size.width() * 0.8660 ) / -2.0, size.height() / 4.0 );
729 mPainterPath.lineTo( 0, size.height() / 2.0 );
730 mPainterPath.lineTo( ( size.width() * 0.8660 ) / 2.0, size.height() / 4.0 );
731 return;
732
733 case Octagon:
734 {
735 static constexpr double VERTEX_OFFSET_FROM_ORIGIN = 1.0 / ( 1 + M_SQRT2 );
736 mPainterPath.moveTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0, size.height() / 2.0 );
737 mPainterPath.lineTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0, size.height() / 2.0 );
738 mPainterPath.lineTo( size.width() / 2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0 );
739 mPainterPath.lineTo( size.width() / 2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0 );
740 mPainterPath.lineTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0, size.height() / -2.0 );
741 mPainterPath.lineTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0, size.height() / -2.0 );
742 mPainterPath.lineTo( size.width() / -2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0 );
743 mPainterPath.lineTo( size.width() / -2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0 );
744 mPainterPath.lineTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0, size.height() / 2.0 );
745 return;
746 }
747
748 case Star:
749 {
750 const double inner_r = std::cos( DEG2RAD( 72.0 ) ) / std::cos( DEG2RAD( 36.0 ) );
751 mPainterPath.moveTo( ( size.width() * inner_r * std::sin( DEG2RAD( 324.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 324.0 ) ) ) / -2.0 );
752 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 288.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 288.0 ) ) ) / -2.0 );
753 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 252.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 252.0 ) ) ) / -2.0 );
754 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 216.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 216.0 ) ) ) / -2.0 );
755 mPainterPath.lineTo( 0, ( size.height() * inner_r ) / 2.0 );
756 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 144.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 144.0 ) ) ) / -2.0 );
757 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 108.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 108.0 ) ) ) / -2.0 );
758 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 72.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 72.0 ) ) ) / -2.0 );
759 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 36.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 36.0 ) ) ) / -2.0 );
760 mPainterPath.lineTo( 0, size.height() / -2.0 );
761 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 324.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 324.0 ) ) ) / -2.0 );
762 return;
763 }
764 }
765}
766
768{
769 switch ( shape )
770 {
771 case Circle:
772 case Rectangle:
773 case Diamond:
774 case Triangle:
776 case LeftHalfTriangle:
777 case SemiCircle:
778 case ThirdCircle:
779 case QuarterCircle:
780 case Pentagon:
781 case Hexagon:
782 case Octagon:
783 case Star:
784 return true;
785
786 case Cross:
787 case Arrow:
788 case HalfArc:
789 return false;
790 }
791
792 return true;
793}
794
796{
797 if ( mSymbolWidth >= mSymbolHeight )
798 {
799 mSymbolHeight = mSymbolHeight * size / mSymbolWidth;
800 mSymbolWidth = size;
801 }
802 else
803 {
804 mSymbolWidth = mSymbolWidth * size / mSymbolHeight;
805 mSymbolHeight = size;
806 }
808}
809
811{
812 mSymbolWidth = w;
813 QgsMarkerSymbolLayer::setSize( mSymbolWidth >= mSymbolHeight ? mSymbolWidth : mSymbolHeight );
814}
815
817{
818 mSymbolHeight = h;
819 QgsMarkerSymbolLayer::setSize( mSymbolWidth >= mSymbolHeight ? mSymbolWidth : mSymbolHeight );
820}
821
823{
825 mSymbolWidthUnit = unit;
826 mSymbolHeightUnit = unit;
827 mStrokeWidthUnit = unit;
828}
829
831{
833 if ( mSymbolWidthUnit != unit || mSymbolHeightUnit != unit || mStrokeWidthUnit != unit )
834 {
836 }
837 return unit;
838}
839
841{
842 return mSymbolWidthUnit == Qgis::RenderUnit::MapUnits || mSymbolWidthUnit == Qgis::RenderUnit::MetersInMapUnits
843 || mSymbolHeightUnit == Qgis::RenderUnit::MapUnits || mSymbolHeightUnit == Qgis::RenderUnit::MetersInMapUnits
844 || mStrokeWidthUnit == Qgis::RenderUnit::MapUnits || mStrokeWidthUnit == Qgis::RenderUnit::MetersInMapUnits
846}
847
849{
851 mSymbolWidthMapUnitScale = scale;
852 mSymbolHeightMapUnitScale = scale;
853 mStrokeWidthMapUnitScale = scale;
854}
855
857{
858 if ( QgsMarkerSymbolLayer::mapUnitScale() == mSymbolWidthMapUnitScale &&
859 mSymbolWidthMapUnitScale == mSymbolHeightMapUnitScale &&
860 mSymbolHeightMapUnitScale == mStrokeWidthMapUnitScale )
861 {
862 return mSymbolWidthMapUnitScale;
863 }
864 return QgsMapUnitScale();
865}
866
868{
869 const QSizeF size = calculateSize( context );
870
871 bool hasDataDefinedRotation = false;
872 QPointF offset;
873 double angle = 0;
874 calculateOffsetAndRotation( context, size.width(), size.height(), hasDataDefinedRotation, offset, angle );
875
876 QTransform transform;
877
878 // move to the desired position
879 transform.translate( point.x() + offset.x(), point.y() + offset.y() );
880
881 if ( !qgsDoubleNear( angle, 0.0 ) )
882 transform.rotate( angle );
883
884 double penWidth = mStrokeWidth;
886 {
887 context.setOriginalValueVariable( mStrokeWidth );
889
890 if ( !QgsVariantUtils::isNull( exprVal ) )
891 {
892 bool ok;
893 const double strokeWidth = exprVal.toDouble( &ok );
894 if ( ok )
895 {
896 penWidth = strokeWidth;
897 }
898 }
899 }
900 penWidth = context.renderContext().convertToPainterUnits( penWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
901
903 {
906 if ( !QgsVariantUtils::isNull( exprVal ) && exprVal.toString() == "no"_L1 )
907 {
908 penWidth = 0.0;
909 }
910 }
911 else if ( mStrokeStyle == Qt::NoPen )
912 penWidth = 0;
913
914 //antialiasing, add 1 pixel
915 penWidth += 1;
916
917 QRectF symbolBounds = transform.mapRect( QRectF( -size.width() / 2.0,
918 -size.height() / 2.0,
919 size.width(),
920 size.height() ) );
921
922 //extend bounds by pen width / 2.0
923 symbolBounds.adjust( -penWidth / 2.0, -penWidth / 2.0,
924 penWidth / 2.0, penWidth / 2.0 );
925
926 return symbolBounds;
927}
928
929bool QgsEllipseSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
930{
931 //width
932 double symbolWidth = mSymbolWidth;
933
934 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Width ) ) //1. priority: data defined setting on symbol layer le
935 {
936 context.setOriginalValueVariable( mSymbolWidth );
938 }
939 if ( mSymbolWidthUnit == Qgis::RenderUnit::Millimeters )
940 {
941 symbolWidth *= mmMapUnitScaleFactor;
942 }
943
944 //height
945 double symbolHeight = mSymbolHeight;
946 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Height ) ) //1. priority: data defined setting on symbol layer level
947 {
948 context.setOriginalValueVariable( mSymbolHeight );
950 }
951 if ( mSymbolHeightUnit == Qgis::RenderUnit::Millimeters )
952 {
953 symbolHeight *= mmMapUnitScaleFactor;
954 }
955
956 //stroke width
957 double strokeWidth = mStrokeWidth;
958
960 {
961 context.setOriginalValueVariable( mStrokeWidth );
963 }
964 if ( mStrokeWidthUnit == Qgis::RenderUnit::Millimeters )
965 {
967 }
968
969 //fill color
970 QColor fc = mColor;
972 {
975 }
976
977 //stroke color
978 QColor oc = mStrokeColor;
980 {
983 }
984
985 //symbol name
988 {
991 }
992
993 //offset
994 double offsetX = 0;
995 double offsetY = 0;
996 markerOffset( context, offsetX, offsetY );
997 QPointF off( offsetX, offsetY );
998
999 //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
1000 double rotation = 0.0;
1002 {
1005 }
1006 else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
1007 {
1008 rotation = mAngle + mLineAngle;
1009 }
1010 rotation = -rotation; //rotation in Qt is counterclockwise
1011 if ( rotation )
1012 off = _rotatedOffset( off, rotation );
1013
1014 QTransform t;
1015 t.translate( shift.x() + offsetX, shift.y() + offsetY );
1016
1017 if ( !qgsDoubleNear( rotation, 0.0 ) )
1018 t.rotate( rotation );
1019
1020 const double halfWidth = symbolWidth / 2.0;
1021 const double halfHeight = symbolHeight / 2.0;
1022
1023 switch ( shape )
1024 {
1025 case Circle:
1026 {
1027 if ( qgsDoubleNear( halfWidth, halfHeight ) )
1028 {
1029 const QgsPoint pt( t.map( QPointF( 0, 0 ) ) );
1030 e.writeFilledCircle( layerName, oc, pt, halfWidth );
1031 }
1032 else
1033 {
1034 QgsPointSequence line;
1035
1036 const double stepsize = 2 * M_PI / 40;
1037 for ( int i = 0; i < 39; ++i )
1038 {
1039 const double angle = stepsize * i;
1040 const double x = halfWidth * std::cos( angle );
1041 const double y = halfHeight * std::sin( angle );
1042 line << QgsPoint( t.map( QPointF( x, y ) ) );
1043 }
1044 //close ellipse with first point
1045 line << line.at( 0 );
1046
1047 if ( mBrush.style() != Qt::NoBrush )
1048 e.writePolygon( QgsRingSequence() << line, layerName, u"SOLID"_s, fc );
1049 if ( mPen.style() != Qt::NoPen )
1050 e.writePolyline( line, layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1051 }
1052 return true;
1053 }
1054
1055 case Rectangle:
1056 {
1058 p << QgsPoint( t.map( QPointF( -halfWidth, -halfHeight ) ) )
1059 << QgsPoint( t.map( QPointF( halfWidth, -halfHeight ) ) )
1060 << QgsPoint( t.map( QPointF( halfWidth, halfHeight ) ) )
1061 << QgsPoint( t.map( QPointF( -halfWidth, halfHeight ) ) );
1062 p << p[0];
1063
1064 if ( mBrush.style() != Qt::NoBrush )
1065 e.writePolygon( QgsRingSequence() << p, layerName, u"SOLID"_s, fc );
1066 if ( mPen.style() != Qt::NoPen )
1067 e.writePolyline( p, layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1068 return true;
1069 }
1070 case Cross:
1071 {
1072 if ( mPen.style() != Qt::NoPen )
1073 {
1075 << QgsPoint( t.map( QPointF( -halfWidth, 0 ) ) )
1076 << QgsPoint( t.map( QPointF( halfWidth, 0 ) ) ),
1077 layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1079 << QgsPoint( t.map( QPointF( 0, halfHeight ) ) )
1080 << QgsPoint( t.map( QPointF( 0, -halfHeight ) ) ),
1081 layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1082 return true;
1083 }
1084 break;
1085 }
1086
1087 case Triangle:
1088 {
1090 p << QgsPoint( t.map( QPointF( -halfWidth, -halfHeight ) ) )
1091 << QgsPoint( t.map( QPointF( halfWidth, -halfHeight ) ) )
1092 << QgsPoint( t.map( QPointF( 0, halfHeight ) ) );
1093 p << p[0];
1094 if ( mBrush.style() != Qt::NoBrush )
1095 e.writePolygon( QgsRingSequence() << p, layerName, u"SOLID"_s, fc );
1096 if ( mPen.style() != Qt::NoPen )
1097 e.writePolyline( p, layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1098 return true;
1099 }
1100
1101 case Diamond:
1102 case Arrow:
1103 case HalfArc:
1104 case RightHalfTriangle:
1105 case LeftHalfTriangle:
1106 case SemiCircle:
1107 case ThirdCircle:
1108 case QuarterCircle:
1109 case Pentagon:
1110 case Hexagon:
1111 case Octagon:
1112 case Star:
1113 return false;
1114 }
1115
1116 return false;
1117}
1118
1120{
1121 if ( ok )
1122 *ok = true;
1123 const QString cleaned = name.toLower().trimmed();
1124
1125 if ( cleaned == "circle"_L1 )
1126 return Circle;
1127 else if ( cleaned == "square"_L1 || cleaned == "rectangle"_L1 )
1128 return Rectangle;
1129 else if ( cleaned == "diamond"_L1 )
1130 return Diamond;
1131 else if ( cleaned == "cross"_L1 )
1132 return Cross;
1133 else if ( cleaned == "arrow"_L1 )
1134 return Arrow;
1135 else if ( cleaned == "half_arc"_L1 )
1136 return HalfArc;
1137 else if ( cleaned == "triangle"_L1 )
1138 return Triangle;
1139 else if ( cleaned == "right_half_triangle"_L1 )
1140 return RightHalfTriangle;
1141 else if ( cleaned == "left_half_triangle"_L1 )
1142 return LeftHalfTriangle;
1143 else if ( cleaned == "semi_circle"_L1 )
1144 return SemiCircle;
1145 else if ( cleaned == "third_circle"_L1 )
1146 return ThirdCircle;
1147 else if ( cleaned == "quarter_circle"_L1 )
1148 return QuarterCircle;
1149 else if ( cleaned == "pentagon"_L1 )
1150 return Pentagon;
1151 else if ( cleaned == "hexagon"_L1 )
1152 return Hexagon;
1153 else if ( cleaned == "octagon"_L1 )
1154 return Octagon;
1155 else if ( cleaned == "star"_L1 )
1156 return Star; if ( ok )
1157 *ok = false;
1158 return Circle;
1159}
1160
1162{
1163 switch ( shape )
1164 {
1165 case Circle:
1166 return u"circle"_s;
1167 case Rectangle:
1168 return u"rectangle"_s;
1169 case Diamond:
1170 return u"diamond"_s;
1171 case Cross:
1172 return u"cross"_s;
1173 case Arrow:
1174 return u"arrow"_s;
1175 case HalfArc:
1176 return u"half_arc"_s;
1177 case Triangle:
1178 return u"triangle"_s;
1179 case RightHalfTriangle:
1180 return u"right_half_triangle"_s;
1181 case LeftHalfTriangle:
1182 return u"left_half_triangle"_s;
1183 case SemiCircle:
1184 return u"semi_circle"_s;
1185 case ThirdCircle:
1186 return u"third_circle"_s;
1187 case QuarterCircle:
1188 return u"quarter_circle"_s;
1189 case Pentagon:
1190 return u"pentagon"_s;
1191 case Hexagon:
1192 return u"hexagon"_s;
1193 case Octagon:
1194 return u"octagon"_s;
1195 case Star:
1196 return u"star"_s;
1197 }
1198 return QString();
1199}
1200
1201QList<QgsEllipseSymbolLayer::Shape> QgsEllipseSymbolLayer::availableShapes()
1202{
1203 QList< Shape > shapes;
1204 shapes << Circle
1205 << Rectangle
1206 << Diamond
1207 << Cross
1208 << Arrow
1209 << HalfArc
1210 << Triangle
1213 << SemiCircle
1214 << ThirdCircle
1215 << QuarterCircle
1216 << Pentagon
1217 << Hexagon
1218 << Octagon
1219 << Star;
1220 return shapes;
1221}
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
Definition qgis.h:789
@ CanCalculateMaskGeometryPerFeature
If present, indicates that mask geometry can safely be calculated per feature for the symbol layer....
Definition qgis.h:901
QFlags< SymbolLayerFlag > SymbolLayerFlags
Symbol layer flags.
Definition qgis.h:906
VerticalAnchorPoint
Marker symbol vertical anchor points.
Definition qgis.h:833
@ Point
Points.
Definition qgis.h:366
RenderUnit
Rendering size units.
Definition qgis.h:5279
@ Millimeters
Millimeters.
Definition qgis.h:5280
@ Unknown
Mixed or unknown units.
Definition qgis.h:5286
@ MapUnits
Map units.
Definition qgis.h:5281
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5287
HorizontalAnchorPoint
Marker symbol horizontal anchor points.
Definition qgis.h:819
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.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
Exports QGIS layers to the DXF format.
void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch).
void writePolygon(const QgsRingSequence &polygon, const QString &layer, const QString &hatchPattern, const QColor &color)
Draw dxf filled polygon (HATCH).
void writePolyline(const QgsPointSequence &line, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Draw dxf primitives (LWPOLYLINE).
void setPenCapStyle(Qt::PenCapStyle style)
Sets the marker's stroke cap style (e.g., flat, round, etc).
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift=QPointF(0.0, 0.0)) const override
write as DXF
void setSymbolHeightMapUnitScale(const QgsMapUnitScale &scale)
void setSymbolWidthMapUnitScale(const QgsMapUnitScale &scale)
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
void setStrokeColor(const QColor &c) override
Sets the stroke color for the symbol layer.
void setStrokeStyle(Qt::PenStyle strokeStyle)
static QgsEllipseSymbolLayer::Shape decodeShape(const QString &name, bool *ok=nullptr)
Attempts to decode a string representation of a shape name to the corresponding shape.
void setStrokeWidthUnit(Qgis::RenderUnit unit)
Sets the units for the symbol's stroke width.
void setSize(double size) override
Sets the symbol size.
QgsMapUnitScale mapUnitScale() const override
Shape
Marker symbol shapes.
@ Cross
Stroke-only cross.
@ HalfArc
Stroke-only half arc.
@ Arrow
Stroke-only arrow.
@ RightHalfTriangle
Right half of a triangle.
@ LeftHalfTriangle
Left half of a triangle.
QColor fillColor() const override
Returns the fill color for the symbol layer.
QgsEllipseSymbolLayer::Shape shape() const
Returns the shape for the rendered ellipse marker symbol.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setFillColor(const QColor &c) override
Sets the fill color for the symbol layer.
void setShape(QgsEllipseSymbolLayer::Shape shape)
Sets the rendered ellipse marker shape.
static QList< QgsEllipseSymbolLayer::Shape > availableShapes()
Returns a list of all available shape types.
Qt::PenStyle strokeStyle() const
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QgsSymbolLayer * createFromSld(QDomElement &element)
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Q_DECL_DEPRECATED void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const override
Saves the symbol layer as SLD.
static QString encodeShape(QgsEllipseSymbolLayer::Shape shape)
Encodes a shape to its string representation.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setSymbolHeightUnit(Qgis::RenderUnit unit)
Sets the units for the symbol's height.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QString layerType() const override
Returns a string that represents this layer type.
QColor strokeColor() const override
Returns the stroke color for the symbol layer.
void setPenJoinStyle(Qt::PenJoinStyle style)
Set stroke join style.
static bool shapeIsFilled(const QgsEllipseSymbolLayer::Shape &shape)
Returns true if a shape has a fill.
void setSymbolWidthUnit(Qgis::RenderUnit unit)
Sets the units for the symbol's width.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
~QgsEllipseSymbolLayer() override
void setMapUnitScale(const QgsMapUnitScale &scale) override
Q_DECL_DEPRECATED void writeSldMarker(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Writes the symbol layer definition as a SLD XML element.
QgsEllipseSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
QgsGeometry geometry
Definition qgsfeature.h:71
Qgis::GeometryType type
double mapRotation() const
Returns the current map rotation in degrees (clockwise).
Struct for storing maximum and minimum scales for measurements in map units.
double mSize
Marker size.
virtual void setSize(double size)
Sets the symbol size.
void setVerticalAnchorPoint(Qgis::VerticalAnchorPoint v)
Sets the vertical anchor point for positioning the symbol.
Qgis::RenderUnit mOffsetUnit
Offset units.
QPointF offset() const
Returns the marker's offset, which is the horizontal and vertical displacement which the rendered mar...
double mLineAngle
Line rotation angle (see setLineAngle() for details).
void setOffsetUnit(Qgis::RenderUnit unit)
Sets the units for the symbol's offset.
void setAngle(double angle)
Sets the rotation angle for the marker.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QPointF mOffset
Marker offset.
QgsMapUnitScale mapUnitScale() const override
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.
double size() const
Returns the symbol size.
QgsMapUnitScale mOffsetMapUnitScale
Offset map unit scale.
Qgis::VerticalAnchorPoint mVerticalAnchorPoint
Vertical anchor point.
static QPointF _rotatedOffset(QPointF offset, double angle)
Adjusts a marker offset to account for rotation.
void setHorizontalAnchorPoint(Qgis::HorizontalAnchorPoint h)
Sets the horizontal anchor point for positioning the symbol.
QgsMapUnitScale mSizeMapUnitScale
Marker size map unit scale.
Qgis::RenderUnit mSizeUnit
Marker size unit.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units for the symbol's size.
void markerOffset(QgsSymbolRenderContext &context, double &offsetX, double &offsetY) const
Calculates the required marker offset, including both the symbol offset and any displacement required...
Qgis::HorizontalAnchorPoint mHorizontalAnchorPoint
Horizontal anchor point.
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol's offset.
double mAngle
Marker rotation angle, in degrees clockwise from north.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
void setMapUnitScale(const QgsMapUnitScale &scale) override
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
A store for object properties.
QString asExpression() const
Returns an expression string representing the state of the property, or an empty string if the proper...
bool isActive() const
Returns whether the property is currently active.
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...
QColor selectionColor() const
Returns the color to use when rendering selected features.
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void setExtraProperties(const QVariantMap &properties)
Sets the open ended set of properties that can drive/inform the SLD encoding.
QVariantMap extraProperties() const
Returns the open ended set of properties that can drive/inform the SLD encoding.
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
static QString encodePenStyle(Qt::PenStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle, double &strokeWidth, double &size)
Extracts properties from an SLD marker definition.
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QString encodeColor(const QColor &color)
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static Q_DECL_DEPRECATED void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
Creates an SLD geometry element.
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
Exports a marker to SLD.
static Qt::PenStyle decodePenStyle(const QString &str)
static Q_DECL_DEPRECATED void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
Creates SLD rotation element.
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
void copyCommonProperties(QgsSymbolLayer *destLayer) const
Copies all common base class properties from this layer to another symbol layer.
bool shouldRenderUsingSelectionColor(const QgsSymbolRenderContext &context) const
Returns true if the symbol layer should be rendered using the selection color from the render context...
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
@ StrokeStyle
Stroke style (eg solid, dashed).
@ Name
Name, eg shape name for simple markers.
@ CapStyle
Line cap style.
@ JoinStyle
Line join style.
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
virtual Qgis::SymbolLayerFlags flags() const
Returns flags which control the symbol layer's behavior.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
QgsSymbolLayer(const QgsSymbolLayer &other)
Encapsulates the context in which a symbol is being rendered.
const QgsFeature * feature() const
Returns the current feature being rendered.
Qgis::SymbolRenderHints renderHints() const
Returns the rendering hint flags for the symbol.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
qreal opacity() const
Returns the opacity for the symbol.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6924
QMap< QString, QString > QgsStringMap
Definition qgis.h:7437
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
#define DEG2RAD(x)
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63