QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 #include "qgsfillsymbol.h"
23 #include "qgsannotationitemnode.h"
25 
28  , mPolygon( polygon )
29  , mSymbol( std::make_unique< QgsFillSymbol >() )
30 {
31 
32 }
33 
35 
37 {
38  return QStringLiteral( "polygon" );
39 }
40 
42 {
43 
44  auto transformRing = [&context]( QPolygonF & pts )
45  {
46  //transform the QPolygonF to screen coordinates
47  if ( context.coordinateTransform().isValid() )
48  {
49  try
50  {
51  context.coordinateTransform().transformPolygon( pts );
52  }
53  catch ( QgsCsException & )
54  {
55  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
56  }
57  }
58 
59  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
60  pts.erase( std::remove_if( pts.begin(), pts.end(),
61  []( const QPointF point )
62  {
63  return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
64  } ), pts.end() );
65 
66  QPointF *ptr = pts.data();
67  for ( int i = 0; i < pts.size(); ++i, ++ptr )
68  {
69  context.mapToPixel().transformInPlace( ptr->rx(), ptr->ry() );
70  }
71  };
72 
73  QPolygonF exterior = mPolygon->exteriorRing()->asQPolygonF();
74  transformRing( exterior );
75  QVector<QPolygonF> rings;
76  rings.reserve( mPolygon->numInteriorRings() );
77  for ( int i = 0; i < mPolygon->numInteriorRings(); ++i )
78  {
79  QPolygonF ring = mPolygon->interiorRing( i )->asQPolygonF();
80  transformRing( ring );
81  rings.append( ring );
82  }
83 
84  mSymbol->startRender( context );
85  mSymbol->renderPolygon( exterior, rings.empty() ? nullptr : &rings, nullptr, context );
86  mSymbol->stopRender( context );
87 }
88 
89 bool QgsAnnotationPolygonItem::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
90 {
91  element.setAttribute( QStringLiteral( "wkt" ), mPolygon->asWkt() );
92  element.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "lineSymbol" ), mSymbol.get(), document, context ) );
93 
94  writeCommonProperties( element, document, context );
95  return true;
96 }
97 
98 QList<QgsAnnotationItemNode> QgsAnnotationPolygonItem::nodes() const
99 {
100  QList< QgsAnnotationItemNode > res;
101 
102  auto processRing = [&res]( const QgsCurve * ring, int ringId )
103  {
104  // we don't want a duplicate node for the closed ring vertex
105  const int count = ring->isClosed() ? ring->numPoints() - 1 : ring->numPoints();
106  res.reserve( res.size() + count );
107  for ( int i = 0; i < count; ++i )
108  {
109  res << QgsAnnotationItemNode( QgsVertexId( 0, ringId, i ), QgsPointXY( ring->xAt( i ), ring->yAt( i ) ), Qgis::AnnotationItemNodeType::VertexHandle );
110  }
111  };
112 
113  if ( const QgsCurve *ring = mPolygon->exteriorRing() )
114  {
115  processRing( ring, 0 );
116  }
117  for ( int i = 0; i < mPolygon->numInteriorRings(); ++i )
118  {
119  processRing( mPolygon->interiorRing( i ), i + 1 );
120  }
121 
122  return res;
123 }
124 
126 {
127  switch ( operation->type() )
128  {
130  {
131  QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
132  if ( mPolygon->moveVertex( moveOperation->nodeId(), QgsPoint( moveOperation->after() ) ) )
134  break;
135  }
136 
138  {
139  QgsAnnotationItemEditOperationDeleteNode *deleteOperation = qgis::down_cast< QgsAnnotationItemEditOperationDeleteNode * >( operation );
140  if ( mPolygon->deleteVertex( deleteOperation->nodeId() ) )
142  break;
143  }
144 
146  {
147  QgsAnnotationItemEditOperationAddNode *addOperation = qgis::down_cast< QgsAnnotationItemEditOperationAddNode * >( operation );
148 
149  QgsPoint segmentPoint;
150  QgsVertexId endOfSegmentVertex;
151  mPolygon->closestSegment( addOperation->point(), segmentPoint, endOfSegmentVertex );
152  if ( mPolygon->insertVertex( endOfSegmentVertex, segmentPoint ) )
154  break;
155  }
156 
158  {
159  QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
160  const QTransform transform = QTransform::fromTranslate( moveOperation->translationX(), moveOperation->translationY() );
161  mPolygon->transform( transform );
163  }
164  }
165 
167 }
168 
170 {
171  switch ( operation->type() )
172  {
174  {
175  QgsAnnotationItemEditOperationMoveNode *moveOperation = dynamic_cast< QgsAnnotationItemEditOperationMoveNode * >( operation );
176  std::unique_ptr< QgsCurvePolygon > modifiedPolygon( mPolygon->clone() );
177  if ( modifiedPolygon->moveVertex( moveOperation->nodeId(), QgsPoint( moveOperation->after() ) ) )
178  {
179  return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry( std::move( modifiedPolygon ) ) );
180  }
181  break;
182  }
183 
185  {
186  QgsAnnotationItemEditOperationTranslateItem *moveOperation = qgis::down_cast< QgsAnnotationItemEditOperationTranslateItem * >( operation );
187  const QTransform transform = QTransform::fromTranslate( moveOperation->translationX(), moveOperation->translationY() );
188  std::unique_ptr< QgsCurvePolygon > modifiedPolygon( mPolygon->clone() );
189  modifiedPolygon->transform( transform );
190  return new QgsAnnotationItemEditOperationTransientResults( QgsGeometry( std::move( modifiedPolygon ) ) );
191  }
192 
195  break;
196  }
197  return nullptr;
198 }
199 
201 {
202  return new QgsAnnotationPolygonItem( new QgsPolygon() );
203 }
204 
205 bool QgsAnnotationPolygonItem::readXml( const QDomElement &element, const QgsReadWriteContext &context )
206 {
207  const QString wkt = element.attribute( QStringLiteral( "wkt" ) );
209  if ( const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( geometry.constGet() ) )
210  mPolygon.reset( polygon->clone() );
211 
212  const QDomElement symbolElem = element.firstChildElement( QStringLiteral( "symbol" ) );
213  if ( !symbolElem.isNull() )
214  setSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( symbolElem, context ) );
215 
216  readCommonProperties( element, context );
217  return true;
218 }
219 
221 {
222  std::unique_ptr< QgsAnnotationPolygonItem > item = std::make_unique< QgsAnnotationPolygonItem >( mPolygon->clone() );
223  item->setSymbol( mSymbol->clone() );
224  item->copyCommonProperties( this );;
225  return item.release();
226 }
227 
229 {
230  return mPolygon->boundingBox();
231 }
232 
234 {
235  return mSymbol.get();
236 }
237 
239 {
240  mSymbol.reset( symbol );
241 }
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
QgsAnnotationPolygonItem::writeXml
bool writeXml(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Writes the item's state into an XML element.
Definition: qgsannotationpolygonitem.cpp:89
QgsAnnotationPolygonItem::clone
QgsAnnotationPolygonItem * clone() override
Returns a clone of the item.
Definition: qgsannotationpolygonitem.cpp:220
QgsAbstractAnnotationItemEditOperation::Type::DeleteNode
@ DeleteNode
Delete a node.
QgsRenderContext::mapToPixel
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
Definition: qgsrendercontext.h:258
QgsPolygon
Polygon geometry type.
Definition: qgspolygon.h:33
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
QgsAnnotationPolygonItem::render
void render(QgsRenderContext &context, QgsFeedback *feedback) override
Renders the item to the specified render context.
Definition: qgsannotationpolygonitem.cpp:41
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
QgsAnnotationItemEditOperationTranslateItem
Annotation item edit operation consisting of translating (moving) an item.
Definition: qgsannotationitemeditoperation.h:182
QgsCurvePolygon
Curve polygon geometry type.
Definition: qgscurvepolygon.h:34
qgsannotationpolygonitem.h
QgsAnnotationItemEditOperationDeleteNode
Annotation item edit operation consisting of deleting a node.
Definition: qgsannotationitemeditoperation.h:120
qgssymbollayerutils.h
QgsGeometry::fromWkt
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QgsAnnotationPolygonItem::transientEditResults
QgsAnnotationItemEditOperationTransientResults * transientEditResults(QgsAbstractAnnotationItemEditOperation *operation) override
Retrieves the results of a transient (in progress) edit operation on the item.
Definition: qgsannotationpolygonitem.cpp:169
QgsAbstractAnnotationItemEditOperation::type
virtual Type type() const =0
Returns the operation type.
QgsAnnotationPolygonItem::~QgsAnnotationPolygonItem
~QgsAnnotationPolygonItem() override
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
QgsCoordinateTransform::isValid
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Definition: qgscoordinatetransform.cpp:900
QgsAnnotationPolygonItem::type
QString type() const override
Returns a unique (untranslated) string identifying the type of item.
Definition: qgsannotationpolygonitem.cpp:36
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsAnnotationItemEditOperationAddNode::point
QgsPoint point() const
Returns the node position (in layer coordinates).
Definition: qgsannotationitemeditoperation.h:168
Qgis::AnnotationItemEditOperationResult
AnnotationItemEditOperationResult
Results from an edit operation on an annotation item.
Definition: qgis.h:1153
Qgis::AnnotationItemEditOperationResult::ItemCleared
@ ItemCleared
The operation results in the item being cleared, and the item should be removed from the layer as a r...
QgsRenderContext::coordinateTransform
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Definition: qgsrendercontext.h:178
QgsAnnotationItemEditOperationMoveNode::nodeId
QgsVertexId nodeId() const
Returns the associated node ID.
Definition: qgsannotationitemeditoperation.h:90
QgsAnnotationPolygonItem::geometry
const QgsCurvePolygon * geometry() const
Returns the geometry of the item.
Definition: qgsannotationpolygonitem.h:78
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsAbstractAnnotationItemEditOperation::Type::TranslateItem
@ TranslateItem
Translate (move) an item.
QgsAnnotationPolygonItem::readXml
bool readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads the item's state from the given DOM element.
Definition: qgsannotationpolygonitem.cpp:205
QgsAnnotationPolygonItem
An annotation item which renders a fill symbol for a polygon geometry.
Definition: qgsannotationpolygonitem.h:32
QgsFeedback
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
QgsAnnotationPolygonItem::symbol
const QgsFillSymbol * symbol() const
Returns the symbol used to render the item.
Definition: qgsannotationpolygonitem.cpp:233
QgsAnnotationItem::writeCommonProperties
bool writeCommonProperties(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const
Writes common properties from the base class into an XML element.
Definition: qgsannotationitem.cpp:48
QgsAnnotationPolygonItem::nodes
QList< QgsAnnotationItemNode > nodes() const override
Returns the nodes for the item, used for editing the item.
Definition: qgsannotationpolygonitem.cpp:98
QgsCurve::yAt
virtual double yAt(int index) const =0
Returns the y-coordinate of the specified node in the line string.
QgsAnnotationItem::readCommonProperties
bool readCommonProperties(const QDomElement &element, const QgsReadWriteContext &context)
Reads common properties from the base class from the given DOM element.
Definition: qgsannotationitem.cpp:56
QgsAnnotationItemEditOperationDeleteNode::nodeId
QgsVertexId nodeId() const
Returns the deleted node ID.
Definition: qgsannotationitemeditoperation.h:135
QgsAnnotationItemEditOperationMoveNode
Annotation item edit operation consisting of moving a node.
Definition: qgsannotationitemeditoperation.h:75
QgsAbstractAnnotationItemEditOperation
Abstract base class for annotation item edit operations.
Definition: qgsannotationitemeditoperation.h:32
QgsCurve::xAt
virtual double xAt(int index) const =0
Returns the x-coordinate of the specified node in the line string.
qgsannotationitemnode.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsAnnotationItemEditOperationMoveNode::after
QgsPoint after() const
Returns the node position after the move occurred (in layer coordinates).
Definition: qgsannotationitemeditoperation.h:104
Qgis::AnnotationItemNodeType::VertexHandle
@ VertexHandle
Node is a handle for manipulating vertices.
QgsMapToPixel::transformInPlace
void transformInPlace(double &x, double &y) const
Transforms device coordinates to map coordinates.
Definition: qgsmaptopixel.h:128
Qgis::AnnotationItemEditOperationResult::Success
@ Success
Item was modified successfully.
QgsAnnotationItemNode
Contains information about a node used for editing an annotation item.
Definition: qgsannotationitemnode.h:31
QgsAbstractAnnotationItemEditOperation::Type::AddNode
@ AddNode
Add a node.
QgsAbstractAnnotationItemEditOperation::Type::MoveNode
@ MoveNode
Move a node.
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:30
QgsFillSymbol
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:29
QgsCoordinateTransform::transformPolygon
void transformPolygon(QPolygonF &polygon, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transforms a polygon to the destination coordinate system.
Definition: qgscoordinatetransform.cpp:421
QgsAnnotationPolygonItem::setSymbol
void setSymbol(QgsFillSymbol *symbol)
Sets the symbol used to render the polygon item.
Definition: qgsannotationpolygonitem.cpp:238
QgsCurve::numPoints
virtual int numPoints() const =0
Returns the number of points in the curve.
QgsCurve::isClosed
virtual bool isClosed() const SIP_HOLDGIL
Returns true if the curve is closed.
Definition: qgscurve.cpp:53
QgsAnnotationPolygonItem::applyEdit
Qgis::AnnotationItemEditOperationResult applyEdit(QgsAbstractAnnotationItemEditOperation *operation) override
Applies an edit operation to the item.
Definition: qgsannotationpolygonitem.cpp:125
QgsAnnotationItemEditOperationAddNode
Annotation item edit operation consisting of adding a node.
Definition: qgsannotationitemeditoperation.h:154
QgsAnnotationItemEditOperationTranslateItem::translationY
double translationY() const
Returns the y-axis translation, in layer units.
Definition: qgsannotationitemeditoperation.h:211
qgsannotationitemeditoperation.h
QgsAnnotationItemEditOperationTranslateItem::translationX
double translationX() const
Returns the x-axis translation, in layer units.
Definition: qgsannotationitemeditoperation.h:204
qgsfillsymbol.h
qgssymbol.h
QgsSymbolLayerUtils::saveSymbol
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Definition: qgssymbollayerutils.cpp:1397
QgsAnnotationPolygonItem::QgsAnnotationPolygonItem
QgsAnnotationPolygonItem(QgsCurvePolygon *polygon)
Constructor for QgsAnnotationPolygonItem, with the specified polygon geometry.
Definition: qgsannotationpolygonitem.cpp:26
QgsAnnotationPolygonItem::boundingBox
QgsRectangle boundingBox() const override
Returns the bounding box of the item's geographic location, in the parent layer's coordinate referenc...
Definition: qgsannotationpolygonitem.cpp:228
QgsAnnotationItem
Abstract base class for annotation items which are drawn with QgsAnnotationLayers.
Definition: qgsannotationitem.h:42
QgsAnnotationItemEditOperationTransientResults
Encapsulates the transient results of an in-progress annotation edit operation.
Definition: qgsannotationitemeditoperation.h:226
QgsAnnotationPolygonItem::create
static QgsAnnotationPolygonItem * create()
Creates a new polygon annotation item.
Definition: qgsannotationpolygonitem.cpp:200
Qgis::AnnotationItemEditOperationResult::Invalid
@ Invalid
Operation has invalid parameters for the item, no change occurred.
qgssurface.h