QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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
262 {
264 const QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::Property::Name, context.renderContext().expressionContext() );
265 if ( !QgsVariantUtils::isNull( exprVal ) )
266 {
267 shape = decodeShape( exprVal.toString() );
268 }
269 preparePath( shape, context, &scaledWidth, &scaledHeight, context.feature() );
270 }
271
272 //offset and rotation
273 bool hasDataDefinedRotation = false;
274 QPointF offset;
275 double angle = 0;
276 calculateOffsetAndRotation( context, scaledWidth, scaledHeight, hasDataDefinedRotation, offset, angle );
277
278 QPainter *p = context.renderContext().painter();
279 if ( !p )
280 {
281 return;
282 }
283
284 QTransform transform;
285 transform.translate( point.x() + offset.x(), point.y() + offset.y() );
286 if ( !qgsDoubleNear( angle, 0.0 ) )
287 {
288 transform.rotate( angle );
289 }
290
291 const bool useSelectedColor = shouldRenderUsingSelectionColor( context );
292 if ( shapeIsFilled( shape ) )
293 {
294 p->setPen( useSelectedColor ? mSelPen : mPen );
295 p->setBrush( useSelectedColor ? mSelBrush : mBrush );
296 }
297 else
298 {
299 p->setPen( useSelectedColor ? mSelPen : mPen );
300 p->setBrush( QBrush() );
301 }
302 p->drawPath( transform.map( mPainterPath ) );
303}
304
305
306void QgsEllipseSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledWidth, double scaledHeight, bool &hasDataDefinedRotation, QPointF &offset, double &angle ) const
307{
308 double offsetX = 0;
309 double offsetY = 0;
310 markerOffset( context, scaledWidth, scaledHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY, mSymbolWidthMapUnitScale, mSymbolHeightMapUnitScale );
311 offset = QPointF( offsetX, offsetY );
312
313 //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
314 const bool ok = true;
316 bool usingDataDefinedRotation = false;
318 {
321 usingDataDefinedRotation = ok;
322 }
323
324 hasDataDefinedRotation = context.renderHints() & Qgis::SymbolRenderHint::DynamicRotation || usingDataDefinedRotation;
325 if ( hasDataDefinedRotation )
326 {
327 // For non-point markers, "dataDefinedRotation" means following the
328 // shape (shape-data defined). For them, "field-data defined" does
329 // not work at all. TODO: if "field-data defined" ever gets implemented
330 // we'll need a way to distinguish here between the two, possibly
331 // using another flag in renderHints()
332 const QgsFeature *f = context.feature();
333 if ( f )
334 {
335 const QgsGeometry g = f->geometry();
336 if ( !g.isNull() && g.type() == Qgis::GeometryType::Point )
337 {
338 const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
339 angle += m2p.mapRotation();
340 }
341 }
342 }
343
344 if ( angle )
346}
347
349{
350 return u"EllipseMarker"_s;
351}
352
357
359{
360 QgsMarkerSymbolLayer::startRender( context ); // get anchor point expressions
361 if ( !context.feature() || !dataDefinedProperties().hasActiveProperties() )
362 {
363 preparePath( mShape, context );
364 }
365 mPen.setColor( mStrokeColor );
366 mPen.setStyle( mStrokeStyle );
367 mPen.setJoinStyle( mPenJoinStyle );
368 mPen.setCapStyle( mPenCapStyle );
369 mPen.setWidthF( context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale ) );
370 mBrush.setColor( mColor );
371
372 QColor selBrushColor = context.renderContext().selectionColor();
373 QColor selPenColor = selBrushColor == mColor ? selBrushColor : mStrokeColor;
374 if ( context.opacity() < 1 && !SELECTION_IS_OPAQUE )
375 {
376 selBrushColor.setAlphaF( context.opacity() );
377 selPenColor.setAlphaF( context.opacity() );
378 }
379 mSelBrush = QBrush( selBrushColor );
380 mSelPen = QPen( !shapeIsFilled( mShape ) ? selBrushColor : selPenColor );
381 mSelPen.setStyle( mStrokeStyle );
382 mSelPen.setWidthF( context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale ) );
383}
384
387
389{
395 m->setShape( mShape );
396 m->setSymbolWidth( mSymbolWidth );
397 m->setSymbolHeight( mSymbolHeight );
398 m->setStrokeStyle( mStrokeStyle );
399 m->setOffset( mOffset );
400 m->setStrokeStyle( mStrokeStyle );
401 m->setPenJoinStyle( mPenJoinStyle );
402 m->setPenCapStyle( mPenCapStyle );
403 m->setStrokeWidth( mStrokeWidth );
404 m->setColor( color() );
405 m->setStrokeColor( mStrokeColor );
406 m->setSymbolWidthUnit( mSymbolWidthUnit );
407 m->setSymbolWidthMapUnitScale( mSymbolWidthMapUnitScale );
408 m->setSymbolHeightUnit( mSymbolHeightUnit );
409 m->setSymbolHeightMapUnitScale( mSymbolHeightMapUnitScale );
410 m->setStrokeWidthUnit( mStrokeWidthUnit );
411 m->setStrokeWidthMapUnitScale( mStrokeWidthMapUnitScale );
412 m->setAngle( mAngle );
415
417 return m;
418}
419
420void QgsEllipseSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
421{
422 QgsSldExportContext context;
423 context.setExtraProperties( props );
424 toSld( doc, element, context );
425}
426
427bool QgsEllipseSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, QgsSldExportContext &context ) const
428{
429 QDomElement symbolizerElem = doc.createElement( u"se:PointSymbolizer"_s );
430 const QVariantMap props = context.extraProperties();
431 if ( !props.value( u"uom"_s, QString() ).toString().isEmpty() )
432 symbolizerElem.setAttribute( u"uom"_s, props.value( u"uom"_s, QString() ).toString() );
433 element.appendChild( symbolizerElem );
434
435 // <Geometry>
436 QgsSymbolLayerUtils::createGeometryElement( doc, symbolizerElem, props.value( u"geom"_s, QString() ).toString(), context );
437
438 return writeSldMarker( doc, symbolizerElem, context );
439}
440
441void QgsEllipseSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
442{
443 QgsSldExportContext context;
444 context.setExtraProperties( props );
445 writeSldMarker( doc, element, context );
446}
447
448bool QgsEllipseSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, QgsSldExportContext &context ) const
449{
450 // <Graphic>
451 QDomElement graphicElem = doc.createElement( u"se:Graphic"_s );
452 element.appendChild( graphicElem );
453
454 const QVariantMap props = context.extraProperties();
455 const double strokeWidth = QgsSymbolLayerUtils::rescaleUom( mStrokeWidth, mStrokeWidthUnit, props );
456 const double symbolWidth = QgsSymbolLayerUtils::rescaleUom( mSymbolWidth, mSymbolWidthUnit, props );
457 QgsSymbolLayerUtils::wellKnownMarkerToSld( doc, graphicElem, encodeShape( mShape ), mColor, mStrokeColor, mStrokeStyle, context, strokeWidth, symbolWidth );
458
459 // <Rotation>
461
462 QString angleFunc = props.value( u"angle"_s, QString() ).toString();
463 if ( angleFunc.isEmpty() ) // symbol has no angle set
464 {
465 if ( ddRotation && ddRotation.isActive() )
466 {
467 angleFunc = ddRotation.asExpression();
468 }
469 else if ( !qgsDoubleNear( mAngle, 0.0 ) )
470 angleFunc = QString::number( mAngle );
471 }
472 else if ( ddRotation && ddRotation.isActive() )
473 {
474 // the symbol has an angle and the symbol layer have a rotation
475 // property set
476 angleFunc = u"%1 + %2"_s.arg( angleFunc, ddRotation.asExpression() );
477 }
478 else if ( !qgsDoubleNear( mAngle, 0.0 ) )
479 {
480 // both the symbol and the symbol layer have angle value set
481 bool ok;
482 const double angle = angleFunc.toDouble( &ok );
483 if ( !ok )
484 {
485 // its a string (probably a property name or a function)
486 angleFunc = u"%1 + %2"_s.arg( angleFunc ).arg( mAngle );
487 }
488 else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
489 {
490 // it's a double value
491 angleFunc = QString::number( angle + mAngle );
492 }
493 }
494 QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc, context );
495
496 // <Displacement>
499
500 // store w/h factor in a <VendorOption>
501 const double widthHeightFactor = mSymbolWidth / mSymbolHeight;
502 const QDomElement factorElem = QgsSymbolLayerUtils::createVendorOptionElement( doc, u"widthHeightFactor"_s, QString::number( widthHeightFactor ) );
503 graphicElem.appendChild( factorElem );
504 return true;
505}
506
508{
509 QgsDebugMsgLevel( u"Entered."_s, 4 );
510
511 QDomElement graphicElem = element.firstChildElement( u"Graphic"_s );
512 if ( graphicElem.isNull() )
513 return nullptr;
514
515 QString name = u"circle"_s;
516 QColor fillColor, strokeColor;
517 double strokeWidth, size;
518 double widthHeightFactor = 1.0;
519 Qt::PenStyle strokeStyle;
520
521 QgsStringMap vendorOptions = QgsSymbolLayerUtils::getVendorOptionList( graphicElem );
522 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
523 {
524 if ( it.key() == "widthHeightFactor"_L1 )
525 {
526 bool ok;
527 const double v = it.value().toDouble( &ok );
528 if ( ok && !qgsDoubleNear( v, 0.0 ) && v > 0 )
529 widthHeightFactor = v;
530 }
531 }
532
534 return nullptr;
535
536 double scaleFactor = 1.0;
537 const QString uom = element.attribute( u"uom"_s );
538 Qgis::RenderUnit sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( uom, &scaleFactor );
539 size = size * scaleFactor;
540 strokeWidth = strokeWidth * scaleFactor;
541
542 double angle = 0.0;
543 QString angleFunc;
544 if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
545 {
546 bool ok;
547 const double d = angleFunc.toDouble( &ok );
548 if ( ok )
549 angle = d;
550 }
551
553 m->setOutputUnit( sldUnitSize );
554 m->setShape( decodeShape( name ) );
559 m->setSymbolWidth( size );
560 m->setSymbolHeight( size / widthHeightFactor );
561 m->setAngle( angle );
562 return m;
563}
564
566{
567 QVariantMap map;
568 map[u"symbol_name"_s] = encodeShape( mShape );
569 map[u"symbol_width"_s] = QString::number( mSymbolWidth );
570 map[u"symbol_width_unit"_s] = QgsUnitTypes::encodeUnit( mSymbolWidthUnit );
571 map[u"symbol_width_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mSymbolWidthMapUnitScale );
572 map[u"symbol_height"_s] = QString::number( mSymbolHeight );
573 map[u"symbol_height_unit"_s] = QgsUnitTypes::encodeUnit( mSymbolHeightUnit );
574 map[u"symbol_height_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mSymbolHeightMapUnitScale );
575 map[u"angle"_s] = QString::number( mAngle );
576 map[u"outline_style"_s] = QgsSymbolLayerUtils::encodePenStyle( mStrokeStyle );
577 map[u"outline_width"_s] = QString::number( mStrokeWidth );
578 map[u"outline_width_unit"_s] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
579 map[u"outline_width_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
580 map[u"joinstyle"_s] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
581 map[u"cap_style"_s] = QgsSymbolLayerUtils::encodePenCapStyle( mPenCapStyle );
582 map[u"color"_s] = QgsColorUtils::colorToString( mColor );
583 map[u"outline_color"_s] = QgsColorUtils::colorToString( mStrokeColor );
584 map[u"offset"_s] = QgsSymbolLayerUtils::encodePoint( mOffset );
585 map[u"offset_unit"_s] = QgsUnitTypes::encodeUnit( mOffsetUnit );
586 map[u"offset_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
587 map[u"size"_s] = QString::number( mSize );
588 map[u"size_unit"_s] = QgsUnitTypes::encodeUnit( mSizeUnit );
589 map[u"size_map_unit_scale"_s] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
590 map[u"horizontal_anchor_point"_s] = QString::number( static_cast< int >( mHorizontalAnchorPoint ) );
591 map[u"vertical_anchor_point"_s] = QString::number( static_cast< int >( mVerticalAnchorPoint ) );
592 return map;
593}
594
595QSizeF QgsEllipseSymbolLayer::calculateSize( QgsSymbolRenderContext &context, double *scaledWidth, double *scaledHeight )
596{
597 double width = 0;
598
599 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Width ) ) //1. priority: data defined setting on symbol layer le
600 {
601 context.setOriginalValueVariable( mSymbolWidth );
603 }
604 else //2. priority: global width setting
605 {
606 width = mSymbolWidth;
607 }
608 if ( scaledWidth )
609 {
610 *scaledWidth = width;
611 }
612 width = context.renderContext().convertToPainterUnits( width, mSymbolWidthUnit, mSymbolHeightMapUnitScale );
613
614 double height = 0;
615 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Height ) ) //1. priority: data defined setting on symbol layer level
616 {
617 context.setOriginalValueVariable( mSymbolHeight );
618 height = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::Property::Height, context.renderContext().expressionContext(), mSymbolHeight );
619 }
620 else //2. priority: global height setting
621 {
622 height = mSymbolHeight;
623 }
624 if ( scaledHeight )
625 {
626 *scaledHeight = height;
627 }
628 height = context.renderContext().convertToPainterUnits( height, mSymbolHeightUnit, mSymbolHeightMapUnitScale );
629 return QSizeF( width, height );
630}
631
632void QgsEllipseSymbolLayer::preparePath( const QgsEllipseSymbolLayer::Shape &shape, QgsSymbolRenderContext &context, double *scaledWidth, double *scaledHeight, const QgsFeature * )
633{
634 mPainterPath = QPainterPath();
635
636 const QSizeF size = calculateSize( context, scaledWidth, scaledHeight );
637
638 switch ( shape )
639 {
640 case Circle:
641 mPainterPath.addEllipse( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) );
642 return;
643
644 case SemiCircle:
645 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 0, 180 );
646 mPainterPath.lineTo( 0, 0 );
647 return;
648
649 case ThirdCircle:
650 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 90, 120 );
651 mPainterPath.lineTo( 0, 0 );
652 return;
653
654 case QuarterCircle:
655 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 90, 90 );
656 mPainterPath.lineTo( 0, 0 );
657 return;
658
659 case Rectangle:
660 mPainterPath.addRect( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) );
661 return;
662
663 case Diamond:
664 mPainterPath.moveTo( -size.width() / 2.0, 0 );
665 mPainterPath.lineTo( 0, size.height() / 2.0 );
666 mPainterPath.lineTo( size.width() / 2.0, 0 );
667 mPainterPath.lineTo( 0, -size.height() / 2.0 );
668 mPainterPath.lineTo( -size.width() / 2.0, 0 );
669 return;
670
671 case Cross:
672 mPainterPath.moveTo( 0, -size.height() / 2.0 );
673 mPainterPath.lineTo( 0, size.height() / 2.0 );
674 mPainterPath.moveTo( -size.width() / 2.0, 0 );
675 mPainterPath.lineTo( size.width() / 2.0, 0 );
676 return;
677
678 case Arrow:
679 mPainterPath.moveTo( -size.width() / 2.0, size.height() / 2.0 );
680 mPainterPath.lineTo( 0, -size.height() / 2.0 );
681 mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
682 return;
683
684 case HalfArc:
685 mPainterPath.moveTo( size.width() / 2.0, 0 );
686 mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 0, 180 );
687 return;
688
689 case Triangle:
690 mPainterPath.moveTo( 0, -size.height() / 2.0 );
691 mPainterPath.lineTo( -size.width() / 2.0, size.height() / 2.0 );
692 mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
693 mPainterPath.lineTo( 0, -size.height() / 2.0 );
694 return;
695
696 case LeftHalfTriangle:
697 mPainterPath.moveTo( 0, size.height() / 2.0 );
698 mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
699 mPainterPath.lineTo( 0, -size.height() / 2.0 );
700 mPainterPath.lineTo( 0, size.height() / 2.0 );
701 return;
702
704 mPainterPath.moveTo( -size.width() / 2.0, size.height() / 2.0 );
705 mPainterPath.lineTo( 0, size.height() / 2.0 );
706 mPainterPath.lineTo( 0, -size.height() / 2.0 );
707 mPainterPath.lineTo( -size.width() / 2.0, size.height() / 2.0 );
708 return;
709
710 case Pentagon:
711 mPainterPath.moveTo( ( size.width() * -0.9511 ) / 2.0, size.height() / ( 2 / -0.309 ) );
712 mPainterPath.lineTo( ( size.width() * -0.5878 ) / 2.0, size.height() / ( 2 / 0.8090 ) );
713 mPainterPath.lineTo( ( size.width() * 0.5878 ) / 2.0, size.height() / ( 2 / 0.8090 ) );
714 mPainterPath.lineTo( ( size.width() * 0.9511 ) / 2.0, size.height() / ( 2 / -0.309 ) );
715 mPainterPath.lineTo( 0, size.height() / -2.0 );
716 mPainterPath.lineTo( ( size.width() * -0.9511 ) / 2.0, size.height() / ( 2 / -0.309 ) );
717 return;
718
719 case Hexagon:
720 mPainterPath.moveTo( ( size.width() * 0.8660 ) / 2.0, size.height() / 4.0 );
721 mPainterPath.lineTo( ( size.width() * 0.8660 ) / 2.0, size.height() / -4.0 );
722 mPainterPath.lineTo( 0, size.height() / -2.0 );
723 mPainterPath.lineTo( ( size.width() * 0.8660 ) / -2.0, size.height() / -4.0 );
724 mPainterPath.lineTo( ( size.width() * 0.8660 ) / -2.0, size.height() / 4.0 );
725 mPainterPath.lineTo( 0, size.height() / 2.0 );
726 mPainterPath.lineTo( ( size.width() * 0.8660 ) / 2.0, size.height() / 4.0 );
727 return;
728
729 case Octagon:
730 {
731 static constexpr double VERTEX_OFFSET_FROM_ORIGIN = 1.0 / ( 1 + M_SQRT2 );
732 mPainterPath.moveTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0, size.height() / 2.0 );
733 mPainterPath.lineTo( ( size.width() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0, size.height() / 2.0 );
734 mPainterPath.lineTo( size.width() / 2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / 2.0 );
735 mPainterPath.lineTo( size.width() / 2.0, ( size.height() * VERTEX_OFFSET_FROM_ORIGIN ) / -2.0 );
736 mPainterPath.lineTo( ( 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 return;
742 }
743
744 case Star:
745 {
746 const double inner_r = std::cos( DEG2RAD( 72.0 ) ) / std::cos( DEG2RAD( 36.0 ) );
747 mPainterPath.moveTo( ( size.width() * inner_r * std::sin( DEG2RAD( 324.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 324.0 ) ) ) / -2.0 );
748 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 288.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 288.0 ) ) ) / -2.0 );
749 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 252.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 252.0 ) ) ) / -2.0 );
750 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 216.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 216.0 ) ) ) / -2.0 );
751 mPainterPath.lineTo( 0, ( size.height() * inner_r ) / 2.0 );
752 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 144.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 144.0 ) ) ) / -2.0 );
753 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 108.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 108.0 ) ) ) / -2.0 );
754 mPainterPath.lineTo( ( size.width() * std::sin( DEG2RAD( 72.0 ) ) ) / 2.0, ( size.height() * std::cos( DEG2RAD( 72.0 ) ) ) / -2.0 );
755 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 36.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 36.0 ) ) ) / -2.0 );
756 mPainterPath.lineTo( 0, size.height() / -2.0 );
757 mPainterPath.lineTo( ( size.width() * inner_r * std::sin( DEG2RAD( 324.0 ) ) ) / 2.0, ( size.height() * inner_r * std::cos( DEG2RAD( 324.0 ) ) ) / -2.0 );
758 return;
759 }
760 }
761}
762
764{
765 switch ( shape )
766 {
767 case Circle:
768 case Rectangle:
769 case Diamond:
770 case Triangle:
772 case LeftHalfTriangle:
773 case SemiCircle:
774 case ThirdCircle:
775 case QuarterCircle:
776 case Pentagon:
777 case Hexagon:
778 case Octagon:
779 case Star:
780 return true;
781
782 case Cross:
783 case Arrow:
784 case HalfArc:
785 return false;
786 }
787
788 return true;
789}
790
792{
793 if ( mSymbolWidth >= mSymbolHeight )
794 {
795 mSymbolHeight = mSymbolHeight * size / mSymbolWidth;
796 mSymbolWidth = size;
797 }
798 else
799 {
800 mSymbolWidth = mSymbolWidth * size / mSymbolHeight;
801 mSymbolHeight = size;
802 }
804}
805
807{
808 mSymbolWidth = w;
809 QgsMarkerSymbolLayer::setSize( mSymbolWidth >= mSymbolHeight ? mSymbolWidth : mSymbolHeight );
810}
811
813{
814 mSymbolHeight = h;
815 QgsMarkerSymbolLayer::setSize( mSymbolWidth >= mSymbolHeight ? mSymbolWidth : mSymbolHeight );
816}
817
819{
821 mSymbolWidthUnit = unit;
822 mSymbolHeightUnit = unit;
823 mStrokeWidthUnit = unit;
824}
825
827{
829 if ( mSymbolWidthUnit != unit || mSymbolHeightUnit != unit || mStrokeWidthUnit != unit )
830 {
832 }
833 return unit;
834}
835
837{
838 return mSymbolWidthUnit == Qgis::RenderUnit::MapUnits
839 || mSymbolWidthUnit == Qgis::RenderUnit::MetersInMapUnits
840 || mSymbolHeightUnit == Qgis::RenderUnit::MapUnits
841 || mSymbolHeightUnit == Qgis::RenderUnit::MetersInMapUnits
842 || mStrokeWidthUnit == Qgis::RenderUnit::MapUnits
843 || mStrokeWidthUnit == Qgis::RenderUnit::MetersInMapUnits
846}
847
849{
851 mSymbolWidthMapUnitScale = scale;
852 mSymbolHeightMapUnitScale = scale;
853 mStrokeWidthMapUnitScale = scale;
854}
855
857{
858 if ( QgsMarkerSymbolLayer::mapUnitScale() == mSymbolWidthMapUnitScale && mSymbolWidthMapUnitScale == mSymbolHeightMapUnitScale && mSymbolHeightMapUnitScale == mStrokeWidthMapUnitScale )
859 {
860 return mSymbolWidthMapUnitScale;
861 }
862 return QgsMapUnitScale();
863}
864
866{
867 const QSizeF size = calculateSize( context );
868
869 bool hasDataDefinedRotation = false;
870 QPointF offset;
871 double angle = 0;
872 calculateOffsetAndRotation( context, size.width(), size.height(), hasDataDefinedRotation, offset, angle );
873
874 QTransform transform;
875
876 // move to the desired position
877 transform.translate( point.x() + offset.x(), point.y() + offset.y() );
878
879 if ( !qgsDoubleNear( angle, 0.0 ) )
880 transform.rotate( angle );
881
882 double penWidth = mStrokeWidth;
884 {
885 context.setOriginalValueVariable( mStrokeWidth );
887
888 if ( !QgsVariantUtils::isNull( exprVal ) )
889 {
890 bool ok;
891 const double strokeWidth = exprVal.toDouble( &ok );
892 if ( ok )
893 {
894 penWidth = strokeWidth;
895 }
896 }
897 }
898 penWidth = context.renderContext().convertToPainterUnits( penWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
899
901 {
904 if ( !QgsVariantUtils::isNull( exprVal ) && exprVal.toString() == "no"_L1 )
905 {
906 penWidth = 0.0;
907 }
908 }
909 else if ( mStrokeStyle == Qt::NoPen )
910 penWidth = 0;
911
912 //antialiasing, add 1 pixel
913 penWidth += 1;
914
915 QRectF symbolBounds = transform.mapRect( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) );
916
917 //extend bounds by pen width / 2.0
918 symbolBounds.adjust( -penWidth / 2.0, -penWidth / 2.0, penWidth / 2.0, penWidth / 2.0 );
919
920 return symbolBounds;
921}
922
923bool QgsEllipseSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
924{
925 //width
926 double symbolWidth = mSymbolWidth;
927
928 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Width ) ) //1. priority: data defined setting on symbol layer le
929 {
930 context.setOriginalValueVariable( mSymbolWidth );
932 }
933 if ( mSymbolWidthUnit == Qgis::RenderUnit::Millimeters )
934 {
935 symbolWidth *= mmMapUnitScaleFactor;
936 }
937
938 //height
939 double symbolHeight = mSymbolHeight;
940 if ( mDataDefinedProperties.isActive( QgsSymbolLayer::Property::Height ) ) //1. priority: data defined setting on symbol layer level
941 {
942 context.setOriginalValueVariable( mSymbolHeight );
944 }
945 if ( mSymbolHeightUnit == Qgis::RenderUnit::Millimeters )
946 {
947 symbolHeight *= mmMapUnitScaleFactor;
948 }
949
950 //stroke width
951 double strokeWidth = mStrokeWidth;
952
954 {
955 context.setOriginalValueVariable( mStrokeWidth );
957 }
958 if ( mStrokeWidthUnit == Qgis::RenderUnit::Millimeters )
959 {
961 }
962
963 //fill color
964 QColor fc = mColor;
966 {
969 }
970
971 //stroke color
972 QColor oc = mStrokeColor;
974 {
977 }
978
979 //symbol name
982 {
985 }
986
987 //offset
988 double offsetX = 0;
989 double offsetY = 0;
990 markerOffset( context, offsetX, offsetY );
991 QPointF off( offsetX, offsetY );
992
993 //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
994 double rotation = 0.0;
996 {
999 }
1000 else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
1001 {
1002 rotation = mAngle + mLineAngle;
1003 }
1004 rotation = -rotation; //rotation in Qt is counterclockwise
1005 if ( rotation )
1006 off = _rotatedOffset( off, rotation );
1007
1008 QTransform t;
1009 t.translate( shift.x() + offsetX, shift.y() + offsetY );
1010
1011 if ( !qgsDoubleNear( rotation, 0.0 ) )
1012 t.rotate( rotation );
1013
1014 const double halfWidth = symbolWidth / 2.0;
1015 const double halfHeight = symbolHeight / 2.0;
1016
1017 switch ( shape )
1018 {
1019 case Circle:
1020 {
1021 if ( qgsDoubleNear( halfWidth, halfHeight ) )
1022 {
1023 const QgsPoint pt( t.map( QPointF( 0, 0 ) ) );
1024 e.writeFilledCircle( layerName, oc, pt, halfWidth );
1025 }
1026 else
1027 {
1028 QgsPointSequence line;
1029
1030 const double stepsize = 2 * M_PI / 40;
1031 for ( int i = 0; i < 39; ++i )
1032 {
1033 const double angle = stepsize * i;
1034 const double x = halfWidth * std::cos( angle );
1035 const double y = halfHeight * std::sin( angle );
1036 line << QgsPoint( t.map( QPointF( x, y ) ) );
1037 }
1038 //close ellipse with first point
1039 line << line.at( 0 );
1040
1041 if ( mBrush.style() != Qt::NoBrush )
1042 e.writePolygon( QgsRingSequence() << line, layerName, u"SOLID"_s, fc );
1043 if ( mPen.style() != Qt::NoPen )
1044 e.writePolyline( line, layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1045 }
1046 return true;
1047 }
1048
1049 case Rectangle:
1050 {
1052 p
1053 << QgsPoint( t.map( QPointF( -halfWidth, -halfHeight ) ) )
1054 << QgsPoint( t.map( QPointF( halfWidth, -halfHeight ) ) )
1055 << QgsPoint( t.map( QPointF( halfWidth, halfHeight ) ) )
1056 << QgsPoint( t.map( QPointF( -halfWidth, halfHeight ) ) );
1057 p << p[0];
1058
1059 if ( mBrush.style() != Qt::NoBrush )
1060 e.writePolygon( QgsRingSequence() << p, layerName, u"SOLID"_s, fc );
1061 if ( mPen.style() != Qt::NoPen )
1062 e.writePolyline( p, layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1063 return true;
1064 }
1065 case Cross:
1066 {
1067 if ( mPen.style() != Qt::NoPen )
1068 {
1069 e.writePolyline( QgsPointSequence() << QgsPoint( t.map( QPointF( -halfWidth, 0 ) ) ) << QgsPoint( t.map( QPointF( halfWidth, 0 ) ) ), layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1070 e.writePolyline( QgsPointSequence() << QgsPoint( t.map( QPointF( 0, halfHeight ) ) ) << QgsPoint( t.map( QPointF( 0, -halfHeight ) ) ), layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1071 return true;
1072 }
1073 break;
1074 }
1075
1076 case Triangle:
1077 {
1079 p << QgsPoint( t.map( QPointF( -halfWidth, -halfHeight ) ) ) << QgsPoint( t.map( QPointF( halfWidth, -halfHeight ) ) ) << QgsPoint( t.map( QPointF( 0, halfHeight ) ) );
1080 p << p[0];
1081 if ( mBrush.style() != Qt::NoBrush )
1082 e.writePolygon( QgsRingSequence() << p, layerName, u"SOLID"_s, fc );
1083 if ( mPen.style() != Qt::NoPen )
1084 e.writePolyline( p, layerName, u"CONTINUOUS"_s, oc, strokeWidth );
1085 return true;
1086 }
1087
1088 case Diamond:
1089 case Arrow:
1090 case HalfArc:
1091 case RightHalfTriangle:
1092 case LeftHalfTriangle:
1093 case SemiCircle:
1094 case ThirdCircle:
1095 case QuarterCircle:
1096 case Pentagon:
1097 case Hexagon:
1098 case Octagon:
1099 case Star:
1100 return false;
1101 }
1102
1103 return false;
1104}
1105
1107{
1108 if ( ok )
1109 *ok = true;
1110 const QString cleaned = name.toLower().trimmed();
1111
1112 if ( cleaned == "circle"_L1 )
1113 return Circle;
1114 else if ( cleaned == "square"_L1 || cleaned == "rectangle"_L1 )
1115 return Rectangle;
1116 else if ( cleaned == "diamond"_L1 )
1117 return Diamond;
1118 else if ( cleaned == "cross"_L1 )
1119 return Cross;
1120 else if ( cleaned == "arrow"_L1 )
1121 return Arrow;
1122 else if ( cleaned == "half_arc"_L1 )
1123 return HalfArc;
1124 else if ( cleaned == "triangle"_L1 )
1125 return Triangle;
1126 else if ( cleaned == "right_half_triangle"_L1 )
1127 return RightHalfTriangle;
1128 else if ( cleaned == "left_half_triangle"_L1 )
1129 return LeftHalfTriangle;
1130 else if ( cleaned == "semi_circle"_L1 )
1131 return SemiCircle;
1132 else if ( cleaned == "third_circle"_L1 )
1133 return ThirdCircle;
1134 else if ( cleaned == "quarter_circle"_L1 )
1135 return QuarterCircle;
1136 else if ( cleaned == "pentagon"_L1 )
1137 return Pentagon;
1138 else if ( cleaned == "hexagon"_L1 )
1139 return Hexagon;
1140 else if ( cleaned == "octagon"_L1 )
1141 return Octagon;
1142 else if ( cleaned == "star"_L1 )
1143 return Star;
1144 if ( ok )
1145 *ok = false;
1146 return Circle;
1147}
1148
1150{
1151 switch ( shape )
1152 {
1153 case Circle:
1154 return u"circle"_s;
1155 case Rectangle:
1156 return u"rectangle"_s;
1157 case Diamond:
1158 return u"diamond"_s;
1159 case Cross:
1160 return u"cross"_s;
1161 case Arrow:
1162 return u"arrow"_s;
1163 case HalfArc:
1164 return u"half_arc"_s;
1165 case Triangle:
1166 return u"triangle"_s;
1167 case RightHalfTriangle:
1168 return u"right_half_triangle"_s;
1169 case LeftHalfTriangle:
1170 return u"left_half_triangle"_s;
1171 case SemiCircle:
1172 return u"semi_circle"_s;
1173 case ThirdCircle:
1174 return u"third_circle"_s;
1175 case QuarterCircle:
1176 return u"quarter_circle"_s;
1177 case Pentagon:
1178 return u"pentagon"_s;
1179 case Hexagon:
1180 return u"hexagon"_s;
1181 case Octagon:
1182 return u"octagon"_s;
1183 case Star:
1184 return u"star"_s;
1185 }
1186 return QString();
1187}
1188
1189QList<QgsEllipseSymbolLayer::Shape> QgsEllipseSymbolLayer::availableShapes()
1190{
1191 QList< Shape > shapes;
1193 return shapes;
1194}
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
Definition qgis.h:796
@ CanCalculateMaskGeometryPerFeature
If present, indicates that mask geometry can safely be calculated per feature for the symbol layer....
Definition qgis.h:908
QFlags< SymbolLayerFlag > SymbolLayerFlags
Symbol layer flags.
Definition qgis.h:913
VerticalAnchorPoint
Marker symbol vertical anchor points.
Definition qgis.h:840
@ Point
Points.
Definition qgis.h:380
RenderUnit
Rendering size units.
Definition qgis.h:5340
@ Millimeters
Millimeters.
Definition qgis.h:5341
@ Unknown
Mixed or unknown units.
Definition qgis.h:5347
@ MapUnits
Map units.
Definition qgis.h:5342
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5348
HorizontalAnchorPoint
Marker symbol horizontal anchor points.
Definition qgis.h:826
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:6975
QMap< QString, QString > QgsStringMap
Definition qgis.h:7475
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
#define DEG2RAD(x)
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63