QGIS API Documentation 3.99.0-Master (d270888f95f)
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 copyPaintEffect( m );
422 return m;
423}
424
425void QgsEllipseSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
426{
427 QgsSldExportContext context;
428 context.setExtraProperties( props );
429 toSld( doc, element, context );
430}
431
432bool QgsEllipseSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, QgsSldExportContext &context ) const
433{
434 QDomElement symbolizerElem = doc.createElement( u"se:PointSymbolizer"_s );
435 const QVariantMap props = context.extraProperties();
436 if ( !props.value( u"uom"_s, QString() ).toString().isEmpty() )
437 symbolizerElem.setAttribute( u"uom"_s, props.value( u"uom"_s, QString() ).toString() );
438 element.appendChild( symbolizerElem );
439
440 // <Geometry>
441 QgsSymbolLayerUtils::createGeometryElement( doc, symbolizerElem, props.value( u"geom"_s, QString() ).toString(), context );
442
443 return writeSldMarker( doc, symbolizerElem, context );
444}
445
446void QgsEllipseSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
447{
448 QgsSldExportContext context;
449 context.setExtraProperties( props );
450 writeSldMarker( doc, element, context );
451}
452
453bool QgsEllipseSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, QgsSldExportContext &context ) const
454{
455 // <Graphic>
456 QDomElement graphicElem = doc.createElement( u"se:Graphic"_s );
457 element.appendChild( graphicElem );
458
459 const QVariantMap props = context.extraProperties();
460 const double strokeWidth = QgsSymbolLayerUtils::rescaleUom( mStrokeWidth, mStrokeWidthUnit, props );
461 const double symbolWidth = QgsSymbolLayerUtils::rescaleUom( mSymbolWidth, mSymbolWidthUnit, props );
462 QgsSymbolLayerUtils::wellKnownMarkerToSld( doc, graphicElem, encodeShape( mShape ), mColor, mStrokeColor, mStrokeStyle, context, strokeWidth, symbolWidth );
463
464 // <Rotation>
466
467 QString angleFunc = props.value( u"angle"_s, QString() ).toString();
468 if ( angleFunc.isEmpty() ) // symbol has no angle set
469 {
470 if ( ddRotation && ddRotation.isActive() )
471 {
472 angleFunc = ddRotation.asExpression();
473 }
474 else if ( !qgsDoubleNear( mAngle, 0.0 ) )
475 angleFunc = QString::number( mAngle );
476 }
477 else if ( ddRotation && ddRotation.isActive() )
478 {
479 // the symbol has an angle and the symbol layer have a rotation
480 // property set
481 angleFunc = u"%1 + %2"_s.arg( angleFunc, ddRotation.asExpression() );
482 }
483 else if ( !qgsDoubleNear( mAngle, 0.0 ) )
484 {
485 // both the symbol and the symbol layer have angle value set
486 bool ok;
487 const double angle = angleFunc.toDouble( &ok );
488 if ( !ok )
489 {
490 // its a string (probably a property name or a function)
491 angleFunc = u"%1 + %2"_s.arg( angleFunc ).arg( mAngle );
492 }
493 else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
494 {
495 // it's a double value
496 angleFunc = QString::number( angle + mAngle );
497 }
498 }
499 QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc, context );
500
501 // <Displacement>
504
505 // store w/h factor in a <VendorOption>
506 const double widthHeightFactor = mSymbolWidth / mSymbolHeight;
507 const QDomElement factorElem = QgsSymbolLayerUtils::createVendorOptionElement( doc, u"widthHeightFactor"_s, QString::number( widthHeightFactor ) );
508 graphicElem.appendChild( factorElem );
509 return true;
510}
511
513{
514 QgsDebugMsgLevel( u"Entered."_s, 4 );
515
516 QDomElement graphicElem = element.firstChildElement( u"Graphic"_s );
517 if ( graphicElem.isNull() )
518 return nullptr;
519
520 QString name = u"circle"_s;
521 QColor fillColor, strokeColor;
522 double strokeWidth, size;
523 double widthHeightFactor = 1.0;
524 Qt::PenStyle strokeStyle;
525
526 QgsStringMap vendorOptions = QgsSymbolLayerUtils::getVendorOptionList( graphicElem );
527 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
528 {
529 if ( it.key() == "widthHeightFactor"_L1 )
530 {
531 bool ok;
532 const double v = it.value().toDouble( &ok );
533 if ( ok && !qgsDoubleNear( v, 0.0 ) && v > 0 )
534 widthHeightFactor = v;
535 }
536 }
537
539 return nullptr;
540
541 double scaleFactor = 1.0;
542 const QString uom = element.attribute( u"uom"_s );
543 Qgis::RenderUnit sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( uom, &scaleFactor );
544 size = size * scaleFactor;
545 strokeWidth = strokeWidth * scaleFactor;
546
547 double angle = 0.0;
548 QString angleFunc;
549 if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
550 {
551 bool ok;
552 const double d = angleFunc.toDouble( &ok );
553 if ( ok )
554 angle = d;
555 }
556
558 m->setOutputUnit( sldUnitSize );
559 m->setShape( decodeShape( name ) );
564 m->setSymbolWidth( size );
565 m->setSymbolHeight( size / widthHeightFactor );
566 m->setAngle( angle );
567 return m;
568}
569
571{
572 QVariantMap map;
573 map[u"symbol_name"_s] = encodeShape( mShape );
574 map[u"symbol_width"_s] = QString::number( mSymbolWidth );
575 map[u"symbol_width_unit"_s] = QgsUnitTypes::encodeUnit( mSymbolWidthUnit );
576 map[u"symbol_width_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mSymbolWidthMapUnitScale );
577 map[u"symbol_height"_s] = QString::number( mSymbolHeight );
578 map[u"symbol_height_unit"_s] = QgsUnitTypes::encodeUnit( mSymbolHeightUnit );
579 map[u"symbol_height_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mSymbolHeightMapUnitScale );
580 map[u"angle"_s] = QString::number( mAngle );
581 map[u"outline_style"_s] = QgsSymbolLayerUtils::encodePenStyle( mStrokeStyle );
582 map[u"outline_width"_s] = QString::number( mStrokeWidth );
583 map[u"outline_width_unit"_s] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
584 map[u"outline_width_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
585 map[u"joinstyle"_s] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
586 map[u"cap_style"_s] = QgsSymbolLayerUtils::encodePenCapStyle( mPenCapStyle );
587 map[u"color"_s] = QgsColorUtils::colorToString( mColor );
588 map[u"outline_color"_s] = QgsColorUtils::colorToString( mStrokeColor );
589 map[u"offset"_s] = QgsSymbolLayerUtils::encodePoint( mOffset );
590 map[u"offset_unit"_s] = QgsUnitTypes::encodeUnit( mOffsetUnit );
591 map[u"offset_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
592 map[u"size"_s] = QString::number( mSize );
593 map[u"size_unit"_s] = QgsUnitTypes::encodeUnit( mSizeUnit );
594 map[u"size_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
595 map[u"horizontal_anchor_point"_s] = QString::number( static_cast< int >( mHorizontalAnchorPoint ) );
596 map[u"vertical_anchor_point"_s] = QString::number( static_cast< int >( mVerticalAnchorPoint ) );
597 return map;
598}
599
600QSizeF QgsEllipseSymbolLayer::calculateSize( QgsSymbolRenderContext &context, double *scaledWidth, double *scaledHeight )
601{
602 double width = 0;
603
604 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Width ) ) //1. priority: data defined setting on symbol layer le
605 {
606 context.setOriginalValueVariable( mSymbolWidth );
608 }
609 else //2. priority: global width setting
610 {
611 width = mSymbolWidth;
612 }
613 if ( scaledWidth )
614 {
615 *scaledWidth = width;
616 }
617 width = context.renderContext().convertToPainterUnits( width, mSymbolWidthUnit, mSymbolHeightMapUnitScale );
618
619 double height = 0;
620 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Height ) ) //1. priority: data defined setting on symbol layer level
621 {
622 context.setOriginalValueVariable( mSymbolHeight );
623 height = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::Property::Height, context.renderContext().expressionContext(), mSymbolHeight );
624 }
625 else //2. priority: global height setting
626 {
627 height = mSymbolHeight;
628 }
629 if ( scaledHeight )
630 {
631 *scaledHeight = height;
632 }
633 height = context.renderContext().convertToPainterUnits( height, mSymbolHeightUnit, mSymbolHeightMapUnitScale );
634 return QSizeF( width, height );
635}
636
637void QgsEllipseSymbolLayer::preparePath( const QgsEllipseSymbolLayer::Shape &shape, QgsSymbolRenderContext &context, double *scaledWidth, double *scaledHeight, const QgsFeature * )
638{
639 mPainterPath = QPainterPath();
640
641 const QSizeF size = calculateSize( context, scaledWidth, scaledHeight );
642
643 switch ( shape )
644 {
645 case Circle:
646 mPainterPath.addEllipse( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) );
647 return;
648
649 case SemiCircle:
650 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 0, 180 );
651 mPainterPath.lineTo( 0, 0 );
652 return;
653
654 case ThirdCircle:
655 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 90, 120 );
656 mPainterPath.lineTo( 0, 0 );
657 return;
658
659 case QuarterCircle:
660 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 90, 90 );
661 mPainterPath.lineTo( 0, 0 );
662 return;
663
664 case Rectangle:
665 mPainterPath.addRect( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) );
666 return;
667
668 case Diamond:
669 mPainterPath.moveTo( -size.width() / 2.0, 0 );
670 mPainterPath.lineTo( 0, size.height() / 2.0 );
671 mPainterPath.lineTo( size.width() / 2.0, 0 );
672 mPainterPath.lineTo( 0, -size.height() / 2.0 );
673 mPainterPath.lineTo( -size.width() / 2.0, 0 );
674 return;
675
676 case Cross:
677 mPainterPath.moveTo( 0, -size.height() / 2.0 );
678 mPainterPath.lineTo( 0, size.height() / 2.0 );
679 mPainterPath.moveTo( -size.width() / 2.0, 0 );
680 mPainterPath.lineTo( size.width() / 2.0, 0 );
681 return;
682
683 case Arrow:
684 mPainterPath.moveTo( -size.width() / 2.0, size.height() / 2.0 );
685 mPainterPath.lineTo( 0, -size.height() / 2.0 );
686 mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
687 return;
688
689 case HalfArc:
690 mPainterPath.moveTo( size.width() / 2.0, 0 );
691 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 0, 180 );
692 return;
693
694 case Triangle:
695 mPainterPath.moveTo( 0, -size.height() / 2.0 );
696 mPainterPath.lineTo( -size.width() / 2.0, size.height() / 2.0 );
697 mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
698 mPainterPath.lineTo( 0, -size.height() / 2.0 );
699 return;
700
701 case LeftHalfTriangle:
702 mPainterPath.moveTo( 0, size.height() / 2.0 );
703 mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
704 mPainterPath.lineTo( 0, -size.height() / 2.0 );
705 mPainterPath.lineTo( 0, size.height() / 2.0 );
706 return;
707
709 mPainterPath.moveTo( -size.width() / 2.0, size.height() / 2.0 );
710 mPainterPath.lineTo( 0, size.height() / 2.0 );
711 mPainterPath.lineTo( 0, -size.height() / 2.0 );
712 mPainterPath.lineTo( -size.width() / 2.0, size.height() / 2.0 );
713 return;
714
715 case Pentagon:
716 mPainterPath.moveTo( ( size.width() * -0.9511 ) / 2.0, size.height() / ( 2 / -0.309 ) );
717 mPainterPath.lineTo( ( size.width() * -0.5878 ) / 2.0, size.height() / ( 2 / 0.8090 ) );
718 mPainterPath.lineTo( ( size.width() * 0.5878 ) / 2.0, size.height() / ( 2 / 0.8090 ) );
719 mPainterPath.lineTo( ( size.width() * 0.9511 ) / 2.0, size.height() / ( 2 / -0.309 ) );
720 mPainterPath.lineTo( 0, size.height() / -2.0 );
721 mPainterPath.lineTo( ( size.width() * -0.9511 ) / 2.0, size.height() / ( 2 / -0.309 ) );
722 return;
723
724 case Hexagon:
725 mPainterPath.moveTo( ( size.width() * 0.8660 ) / 2.0, size.height() / 4.0 );
726 mPainterPath.lineTo( ( size.width() * 0.8660 ) / 2.0, size.height() / -4.0 );
727 mPainterPath.lineTo( 0, size.height() / -2.0 );
728 mPainterPath.lineTo( ( size.width() * 0.8660 ) / -2.0, size.height() / -4.0 );
729 mPainterPath.lineTo( ( size.width() * 0.8660 ) / -2.0, size.height() / 4.0 );
730 mPainterPath.lineTo( 0, size.height() / 2.0 );
731 mPainterPath.lineTo( ( size.width() * 0.8660 ) / 2.0, size.height() / 4.0 );
732 return;
733
734 case Octagon:
735 {
736 static constexpr double VERTEX_OFFSET_FROM_ORIGIN = 1.0 / ( 1 + M_SQRT2 );
737 mPainterPath.moveTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0, size.height() / 2.0 );
738 mPainterPath.lineTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0, size.height() / 2.0 );
739 mPainterPath.lineTo( size.width() / 2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0 );
740 mPainterPath.lineTo( size.width() / 2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0 );
741 mPainterPath.lineTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0, size.height() / -2.0 );
742 mPainterPath.lineTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0, size.height() / -2.0 );
743 mPainterPath.lineTo( size.width() / -2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0 );
744 mPainterPath.lineTo( size.width() / -2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0 );
745 mPainterPath.lineTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0, size.height() / 2.0 );
746 return;
747 }
748
749 case Star:
750 {
751 const double inner_r = std::cos( DEG2RAD( 72.0 ) ) / std::cos( DEG2RAD( 36.0 ) );
752 mPainterPath.moveTo( ( size.width() * inner_r * std::sin( DEG2RAD( 324.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 324.0 ) ) ) / -2.0 );
753 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 288.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 288.0 ) ) ) / -2.0 );
754 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 252.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 252.0 ) ) ) / -2.0 );
755 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 216.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 216.0 ) ) ) / -2.0 );
756 mPainterPath.lineTo( 0, ( size.height() * inner_r ) / 2.0 );
757 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 144.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 144.0 ) ) ) / -2.0 );
758 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 108.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 108.0 ) ) ) / -2.0 );
759 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 72.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 72.0 ) ) ) / -2.0 );
760 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 36.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 36.0 ) ) ) / -2.0 );
761 mPainterPath.lineTo( 0, size.height() / -2.0 );
762 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 324.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 324.0 ) ) ) / -2.0 );
763 return;
764 }
765 }
766}
767
769{
770 switch ( shape )
771 {
772 case Circle:
773 case Rectangle:
774 case Diamond:
775 case Triangle:
777 case LeftHalfTriangle:
778 case SemiCircle:
779 case ThirdCircle:
780 case QuarterCircle:
781 case Pentagon:
782 case Hexagon:
783 case Octagon:
784 case Star:
785 return true;
786
787 case Cross:
788 case Arrow:
789 case HalfArc:
790 return false;
791 }
792
793 return true;
794}
795
797{
798 if ( mSymbolWidth >= mSymbolHeight )
799 {
800 mSymbolHeight = mSymbolHeight * size / mSymbolWidth;
801 mSymbolWidth = size;
802 }
803 else
804 {
805 mSymbolWidth = mSymbolWidth * size / mSymbolHeight;
806 mSymbolHeight = size;
807 }
809}
810
812{
813 mSymbolWidth = w;
814 QgsMarkerSymbolLayer::setSize( mSymbolWidth >= mSymbolHeight ? mSymbolWidth : mSymbolHeight );
815}
816
818{
819 mSymbolHeight = h;
820 QgsMarkerSymbolLayer::setSize( mSymbolWidth >= mSymbolHeight ? mSymbolWidth : mSymbolHeight );
821}
822
824{
826 mSymbolWidthUnit = unit;
827 mSymbolHeightUnit = unit;
828 mStrokeWidthUnit = unit;
829}
830
832{
834 if ( mSymbolWidthUnit != unit || mSymbolHeightUnit != unit || mStrokeWidthUnit != unit )
835 {
837 }
838 return unit;
839}
840
842{
843 return mSymbolWidthUnit == Qgis::RenderUnit::MapUnits || mSymbolWidthUnit == Qgis::RenderUnit::MetersInMapUnits
844 || mSymbolHeightUnit == Qgis::RenderUnit::MapUnits || mSymbolHeightUnit == Qgis::RenderUnit::MetersInMapUnits
845 || mStrokeWidthUnit == Qgis::RenderUnit::MapUnits || mStrokeWidthUnit == Qgis::RenderUnit::MetersInMapUnits
847}
848
850{
852 mSymbolWidthMapUnitScale = scale;
853 mSymbolHeightMapUnitScale = scale;
854 mStrokeWidthMapUnitScale = scale;
855}
856
858{
859 if ( QgsMarkerSymbolLayer::mapUnitScale() == mSymbolWidthMapUnitScale &&
860 mSymbolWidthMapUnitScale == mSymbolHeightMapUnitScale &&
861 mSymbolHeightMapUnitScale == mStrokeWidthMapUnitScale )
862 {
863 return mSymbolWidthMapUnitScale;
864 }
865 return QgsMapUnitScale();
866}
867
869{
870 const QSizeF size = calculateSize( context );
871
872 bool hasDataDefinedRotation = false;
873 QPointF offset;
874 double angle = 0;
875 calculateOffsetAndRotation( context, size.width(), size.height(), hasDataDefinedRotation, offset, angle );
876
877 QTransform transform;
878
879 // move to the desired position
880 transform.translate( point.x() + offset.x(), point.y() + offset.y() );
881
882 if ( !qgsDoubleNear( angle, 0.0 ) )
883 transform.rotate( angle );
884
885 double penWidth = mStrokeWidth;
887 {
888 context.setOriginalValueVariable( mStrokeWidth );
890
891 if ( !QgsVariantUtils::isNull( exprVal ) )
892 {
893 bool ok;
894 const double strokeWidth = exprVal.toDouble( &ok );
895 if ( ok )
896 {
897 penWidth = strokeWidth;
898 }
899 }
900 }
901 penWidth = context.renderContext().convertToPainterUnits( penWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
902
904 {
907 if ( !QgsVariantUtils::isNull( exprVal ) && exprVal.toString() == "no"_L1 )
908 {
909 penWidth = 0.0;
910 }
911 }
912 else if ( mStrokeStyle == Qt::NoPen )
913 penWidth = 0;
914
915 //antialiasing, add 1 pixel
916 penWidth += 1;
917
918 QRectF symbolBounds = transform.mapRect( QRectF( -size.width() / 2.0,
919 -size.height() / 2.0,
920 size.width(),
921 size.height() ) );
922
923 //extend bounds by pen width / 2.0
924 symbolBounds.adjust( -penWidth / 2.0, -penWidth / 2.0,
925 penWidth / 2.0, penWidth / 2.0 );
926
927 return symbolBounds;
928}
929
930bool QgsEllipseSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
931{
932 //width
933 double symbolWidth = mSymbolWidth;
934
935 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Width ) ) //1. priority: data defined setting on symbol layer le
936 {
937 context.setOriginalValueVariable( mSymbolWidth );
939 }
940 if ( mSymbolWidthUnit == Qgis::RenderUnit::Millimeters )
941 {
942 symbolWidth *= mmMapUnitScaleFactor;
943 }
944
945 //height
946 double symbolHeight = mSymbolHeight;
947 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Height ) ) //1. priority: data defined setting on symbol layer level
948 {
949 context.setOriginalValueVariable( mSymbolHeight );
951 }
952 if ( mSymbolHeightUnit == Qgis::RenderUnit::Millimeters )
953 {
954 symbolHeight *= mmMapUnitScaleFactor;
955 }
956
957 //stroke width
958 double strokeWidth = mStrokeWidth;
959
961 {
962 context.setOriginalValueVariable( mStrokeWidth );
964 }
965 if ( mStrokeWidthUnit == Qgis::RenderUnit::Millimeters )
966 {
968 }
969
970 //fill color
971 QColor fc = mColor;
973 {
976 }
977
978 //stroke color
979 QColor oc = mStrokeColor;
981 {
984 }
985
986 //symbol name
989 {
992 }
993
994 //offset
995 double offsetX = 0;
996 double offsetY = 0;
997 markerOffset( context, offsetX, offsetY );
998 QPointF off( offsetX, offsetY );
999
1000 //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
1001 double rotation = 0.0;
1003 {
1006 }
1007 else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
1008 {
1009 rotation = mAngle + mLineAngle;
1010 }
1011 rotation = -rotation; //rotation in Qt is counterclockwise
1012 if ( rotation )
1013 off = _rotatedOffset( off, rotation );
1014
1015 QTransform t;
1016 t.translate( shift.x() + offsetX, shift.y() + offsetY );
1017
1018 if ( !qgsDoubleNear( rotation, 0.0 ) )
1019 t.rotate( rotation );
1020
1021 const double halfWidth = symbolWidth / 2.0;
1022 const double halfHeight = symbolHeight / 2.0;
1023
1024 switch ( shape )
1025 {
1026 case Circle:
1027 {
1028 if ( qgsDoubleNear( halfWidth, halfHeight ) )
1029 {
1030 const QgsPoint pt( t.map( QPointF( 0, 0 ) ) );
1031 e.writeFilledCircle( layerName, oc, pt, halfWidth );
1032 }
1033 else
1034 {
1035 QgsPointSequence line;
1036
1037 const double stepsize = 2 * M_PI / 40;
1038 for ( int i = 0; i < 39; ++i )
1039 {
1040 const double angle = stepsize * i;
1041 const double x = halfWidth * std::cos( angle );
1042 const double y = halfHeight * std::sin( angle );
1043 line << QgsPoint( t.map( QPointF( x, y ) ) );
1044 }
1045 //close ellipse with first point
1046 line << line.at( 0 );
1047
1048 if ( mBrush.style() != Qt::NoBrush )
1049 e.writePolygon( QgsRingSequence() << line, layerName, u"SOLID"_s, fc );
1050 if ( mPen.style() != Qt::NoPen )
1051 e.writePolyline( line, layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1052 }
1053 return true;
1054 }
1055
1056 case Rectangle:
1057 {
1059 p << QgsPoint( t.map( QPointF( -halfWidth, -halfHeight ) ) )
1060 << QgsPoint( t.map( QPointF( halfWidth, -halfHeight ) ) )
1061 << QgsPoint( t.map( QPointF( halfWidth, halfHeight ) ) )
1062 << QgsPoint( t.map( QPointF( -halfWidth, halfHeight ) ) );
1063 p << p[0];
1064
1065 if ( mBrush.style() != Qt::NoBrush )
1066 e.writePolygon( QgsRingSequence() << p, layerName, u"SOLID"_s, fc );
1067 if ( mPen.style() != Qt::NoPen )
1068 e.writePolyline( p, layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1069 return true;
1070 }
1071 case Cross:
1072 {
1073 if ( mPen.style() != Qt::NoPen )
1074 {
1076 << QgsPoint( t.map( QPointF( -halfWidth, 0 ) ) )
1077 << QgsPoint( t.map( QPointF( halfWidth, 0 ) ) ),
1078 layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1080 << QgsPoint( t.map( QPointF( 0, halfHeight ) ) )
1081 << QgsPoint( t.map( QPointF( 0, -halfHeight ) ) ),
1082 layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1083 return true;
1084 }
1085 break;
1086 }
1087
1088 case Triangle:
1089 {
1091 p << QgsPoint( t.map( QPointF( -halfWidth, -halfHeight ) ) )
1092 << QgsPoint( t.map( QPointF( halfWidth, -halfHeight ) ) )
1093 << QgsPoint( t.map( QPointF( 0, halfHeight ) ) );
1094 p << p[0];
1095 if ( mBrush.style() != Qt::NoBrush )
1096 e.writePolygon( QgsRingSequence() << p, layerName, u"SOLID"_s, fc );
1097 if ( mPen.style() != Qt::NoPen )
1098 e.writePolyline( p, layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1099 return true;
1100 }
1101
1102 case Diamond:
1103 case Arrow:
1104 case HalfArc:
1105 case RightHalfTriangle:
1106 case LeftHalfTriangle:
1107 case SemiCircle:
1108 case ThirdCircle:
1109 case QuarterCircle:
1110 case Pentagon:
1111 case Hexagon:
1112 case Octagon:
1113 case Star:
1114 return false;
1115 }
1116
1117 return false;
1118}
1119
1121{
1122 if ( ok )
1123 *ok = true;
1124 const QString cleaned = name.toLower().trimmed();
1125
1126 if ( cleaned == "circle"_L1 )
1127 return Circle;
1128 else if ( cleaned == "square"_L1 || cleaned == "rectangle"_L1 )
1129 return Rectangle;
1130 else if ( cleaned == "diamond"_L1 )
1131 return Diamond;
1132 else if ( cleaned == "cross"_L1 )
1133 return Cross;
1134 else if ( cleaned == "arrow"_L1 )
1135 return Arrow;
1136 else if ( cleaned == "half_arc"_L1 )
1137 return HalfArc;
1138 else if ( cleaned == "triangle"_L1 )
1139 return Triangle;
1140 else if ( cleaned == "right_half_triangle"_L1 )
1141 return RightHalfTriangle;
1142 else if ( cleaned == "left_half_triangle"_L1 )
1143 return LeftHalfTriangle;
1144 else if ( cleaned == "semi_circle"_L1 )
1145 return SemiCircle;
1146 else if ( cleaned == "third_circle"_L1 )
1147 return ThirdCircle;
1148 else if ( cleaned == "quarter_circle"_L1 )
1149 return QuarterCircle;
1150 else if ( cleaned == "pentagon"_L1 )
1151 return Pentagon;
1152 else if ( cleaned == "hexagon"_L1 )
1153 return Hexagon;
1154 else if ( cleaned == "octagon"_L1 )
1155 return Octagon;
1156 else if ( cleaned == "star"_L1 )
1157 return Star; if ( ok )
1158 *ok = false;
1159 return Circle;
1160}
1161
1163{
1164 switch ( shape )
1165 {
1166 case Circle:
1167 return u"circle"_s;
1168 case Rectangle:
1169 return u"rectangle"_s;
1170 case Diamond:
1171 return u"diamond"_s;
1172 case Cross:
1173 return u"cross"_s;
1174 case Arrow:
1175 return u"arrow"_s;
1176 case HalfArc:
1177 return u"half_arc"_s;
1178 case Triangle:
1179 return u"triangle"_s;
1180 case RightHalfTriangle:
1181 return u"right_half_triangle"_s;
1182 case LeftHalfTriangle:
1183 return u"left_half_triangle"_s;
1184 case SemiCircle:
1185 return u"semi_circle"_s;
1186 case ThirdCircle:
1187 return u"third_circle"_s;
1188 case QuarterCircle:
1189 return u"quarter_circle"_s;
1190 case Pentagon:
1191 return u"pentagon"_s;
1192 case Hexagon:
1193 return u"hexagon"_s;
1194 case Octagon:
1195 return u"octagon"_s;
1196 case Star:
1197 return u"star"_s;
1198 }
1199 return QString();
1200}
1201
1202QList<QgsEllipseSymbolLayer::Shape> QgsEllipseSymbolLayer::availableShapes()
1203{
1204 QList< Shape > shapes;
1205 shapes << Circle
1206 << Rectangle
1207 << Diamond
1208 << Cross
1209 << Arrow
1210 << HalfArc
1211 << Triangle
1214 << SemiCircle
1215 << ThirdCircle
1216 << QuarterCircle
1217 << Pentagon
1218 << Hexagon
1219 << Octagon
1220 << Star;
1221 return shapes;
1222}
@ 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:5255
@ Millimeters
Millimeters.
Definition qgis.h:5256
@ Unknown
Mixed or unknown units.
Definition qgis.h:5262
@ MapUnits
Map units.
Definition qgis.h:5257
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5263
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.
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.
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
@ 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.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another 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:6900
QMap< QString, QString > QgsStringMap
Definition qgis.h:7413
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
#define DEG2RAD(x)
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63