QGIS API Documentation  3.17.0-Master (a84647cf30)
qgsannotationpolygonitem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsannotationpolygonitem.cpp
3  ----------------
4  begin : July 2020
5  copyright : (C) 2020 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgssymbol.h"
20 #include "qgssymbollayerutils.h"
21 #include "qgssurface.h"
22 
25  , mPolygon( polygon )
26  , mSymbol( qgis::make_unique< QgsFillSymbol >() )
27 {
28 
29 }
30 
32 
34 {
35  return QStringLiteral( "polygon" );
36 }
37 
39 {
40 
41  auto transformRing = [&context]( QPolygonF & pts )
42  {
43  //transform the QPolygonF to screen coordinates
44  if ( context.coordinateTransform().isValid() )
45  {
46  try
47  {
48  context.coordinateTransform().transformPolygon( pts );
49  }
50  catch ( QgsCsException & )
51  {
52  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
53  }
54  }
55 
56  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
57  pts.erase( std::remove_if( pts.begin(), pts.end(),
58  []( const QPointF point )
59  {
60  return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
61  } ), pts.end() );
62 
63  QPointF *ptr = pts.data();
64  for ( int i = 0; i < pts.size(); ++i, ++ptr )
65  {
66  context.mapToPixel().transformInPlace( ptr->rx(), ptr->ry() );
67  }
68  };
69 
70  QPolygonF exterior = mPolygon->exteriorRing()->asQPolygonF();
71  transformRing( exterior );
72  QVector<QPolygonF> rings;
73  rings.reserve( mPolygon->numInteriorRings() );
74  for ( int i = 0; i < mPolygon->numInteriorRings(); ++i )
75  {
76  QPolygonF ring = mPolygon->interiorRing( i )->asQPolygonF();
77  transformRing( ring );
78  rings.append( ring );
79  }
80 
81  mSymbol->startRender( context );
82  mSymbol->renderPolygon( exterior, rings.empty() ? nullptr : &rings, nullptr, context );
83  mSymbol->stopRender( context );
84 }
85 
86 bool QgsAnnotationPolygonItem::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
87 {
88  element.setAttribute( QStringLiteral( "wkt" ), mPolygon->asWkt() );
89 
90  element.setAttribute( QStringLiteral( "zIndex" ), zIndex() );
91  element.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "lineSymbol" ), mSymbol.get(), document, context ) );
92 
93  return true;
94 }
95 
97 {
98  return new QgsAnnotationPolygonItem( new QgsPolygon() );
99 }
100 
101 bool QgsAnnotationPolygonItem::readXml( const QDomElement &element, const QgsReadWriteContext &context )
102 {
103  const QString wkt = element.attribute( QStringLiteral( "wkt" ) );
105  if ( const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geometry.constGet() ) )
106  mPolygon.reset( polygon->clone() );
107 
108  setZIndex( element.attribute( QStringLiteral( "zIndex" ) ).toInt() );
109 
110  const QDomElement symbolElem = element.firstChildElement( QStringLiteral( "symbol" ) );
111  if ( !symbolElem.isNull() )
112  setSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( symbolElem, context ) );
113 
114  return true;
115 }
116 
118 {
119  std::unique_ptr< QgsAnnotationPolygonItem > item = qgis::make_unique< QgsAnnotationPolygonItem >( mPolygon->clone() );
120  item->setSymbol( mSymbol->clone() );
121  item->setZIndex( zIndex() );
122  return item.release();
123 }
124 
126 {
127  return mPolygon->boundingBox();
128 }
129 
131 {
132  return mSymbol.get();
133 }
134 
136 {
137  mSymbol.reset( symbol );
138 }
The class is used as a container of context for various read/write operations on other objects...
A rectangle specified with double values.
Definition: qgsrectangle.h:41
const QgsFillSymbol * symbol() const
Returns the symbol used to render the item.
void setZIndex(int index)
Sets the item&#39;s z index, which controls the order in which annotation items are rendered in the layer...
bool writeXml(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Writes the item&#39;s state into an XML element.
~QgsAnnotationPolygonItem() override
QgsAnnotationPolygonItem * clone() override
Returns a clone of the item.
Curve polygon geometry type.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:123
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
void transformPolygon(QPolygonF &polygon, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transforms a polygon to the destination coordinate system.
Base class for feedback objects to be used for cancellation of something running in a worker thread...
Definition: qgsfeedback.h:43
void transformInPlace(double &x, double &y) const
Transform device coordinates to map coordinates.
void setSymbol(QgsFillSymbol *symbol)
Sets the symbol used to render the polygon item.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads the item&#39;s state from the given DOM element.
void render(QgsRenderContext &context, QgsFeedback *feedback) override
Renders the item to the specified render context.
QgsRectangle boundingBox() const override
Returns the bounding box of the item&#39;s geographic location, in the parent layer&#39;s coordinate referenc...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
int zIndex() const
Returns the item&#39;s z index, which controls the order in which annotation items are rendered in the la...
Abstract base class for annotation items which are drawn with QgsAnnotationLayers.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QString type() const override
Returns a unique (untranslated) string identifying the type of item.
Contains information about the context of a rendering operation.
const QgsMapToPixel & mapToPixel() const
Returns the context&#39;s map to pixel transform, which transforms between map coordinates and device coo...
An annotation item which renders a fill symbol for a polygon geometry.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1295
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
Polygon geometry type.
Definition: qgspolygon.h:33
const QgsCurvePolygon * geometry() const
Returns the geometry of the item.
QgsAnnotationPolygonItem(QgsCurvePolygon *polygon)
Constructor for QgsAnnotationPolygonItem, with the specified polygon geometry.
static QgsAnnotationPolygonItem * create()
Creates a new polygon annotation item.