QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgspointcloudextentrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointcloudextentrenderer.h
3  --------------------
4  begin : December 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 "qgspointcloudblock.h"
20 #include "qgssymbollayerutils.h"
21 #include "qgssymbol.h"
22 #include "qgswkbtypes.h"
23 #include "qgspolygon.h"
24 #include "qgscurve.h"
25 #include "qgslinesymbollayer.h"
27 
29  : mFillSymbol( symbol ? symbol : defaultFillSymbol() )
30 {
31 
32 }
33 
35 {
36  return QStringLiteral( "extent" );
37 }
38 
40 {
41  std::unique_ptr< QgsPointCloudExtentRenderer > res = qgis::make_unique< QgsPointCloudExtentRenderer >( mFillSymbol ? mFillSymbol->clone() : nullptr );
42  copyCommonProperties( res.get() );
43  return res.release();
44 }
45 
47 {
48 
49 }
50 
52 {
53  std::unique_ptr< QgsPointCloudExtentRenderer > r = qgis::make_unique< QgsPointCloudExtentRenderer >();
54 
55  QDomElement symbolElem = element.firstChildElement( QStringLiteral( "symbol" ) );
56  if ( !symbolElem.isNull() )
57  {
58  r->mFillSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( symbolElem, context ) );
59  }
60 
61  r->restoreCommonProperties( element, context );
62  return r.release();
63 }
64 
66 {
67  auto transformRing = [&context]( QPolygonF & pts )
68  {
69  //transform the QPolygonF to screen coordinates
70  if ( context.renderContext().coordinateTransform().isValid() )
71  {
72  try
73  {
75  }
76  catch ( QgsCsException & )
77  {
78  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
79  }
80  }
81 
82  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
83  pts.erase( std::remove_if( pts.begin(), pts.end(),
84  []( const QPointF point )
85  {
86  return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
87  } ), pts.end() );
88 
89  QPointF *ptr = pts.data();
90  for ( int i = 0; i < pts.size(); ++i, ++ptr )
91  {
92  context.renderContext().mapToPixel().transformInPlace( ptr->rx(), ptr->ry() );
93  }
94  };
95 
96  for ( auto it = extent.const_parts_begin(); it != extent.const_parts_end(); ++it )
97  {
98  if ( const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( *it ) )
99  {
100  QPolygonF exterior = polygon->exteriorRing()->asQPolygonF();
101  transformRing( exterior );
102  QVector<QPolygonF> rings;
103  rings.reserve( polygon->numInteriorRings() );
104  for ( int i = 0; i < polygon->numInteriorRings(); ++i )
105  {
106  QPolygonF ring = polygon->interiorRing( i )->asQPolygonF();
107  transformRing( ring );
108  rings.append( ring );
109  }
110 
111  mFillSymbol->renderPolygon( exterior, rings.empty() ? nullptr : &rings, nullptr, context.renderContext() );
112  }
113  }
114 }
115 
117 {
118  std::unique_ptr< QgsSimpleLineSymbolLayer > layer = qgis::make_unique< QgsSimpleLineSymbolLayer >();
119  layer->setColor( QColor( 228, 26, 28 ) );
120  layer->setWidth( 0.960000 );
121  layer->setPenStyle( Qt::DotLine );
122  layer->setWidthUnit( QgsUnitTypes::RenderMillimeters );
123  return new QgsFillSymbol( QgsSymbolLayerList() << layer.release() );
124 }
125 
127 {
128  return mFillSymbol.get();
129 }
130 
132 {
133  mFillSymbol.reset( symbol );
134 }
135 
136 QDomElement QgsPointCloudExtentRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
137 {
138  QDomElement rendererElem = doc.createElement( QStringLiteral( "renderer" ) );
139 
140  rendererElem.setAttribute( QStringLiteral( "type" ), type() );
141 
142  QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QString(), mFillSymbol.get(), doc, context );
143  rendererElem.appendChild( symbolElem );
144 
145  saveCommonProperties( rendererElem, context );
146  return rendererElem;
147 }
148 
150 {
152  mFillSymbol->startRender( context.renderContext() );
153 }
154 
156 {
158  mFillSymbol->stopRender( context.renderContext() );
159 }
160 
161 QList<QgsLayerTreeModelLegendNode *> QgsPointCloudExtentRenderer::createLegendNodes( QgsLayerTreeLayer *nodeLayer )
162 {
163  QList<QgsLayerTreeModelLegendNode *> nodes;
164 
165  QgsLegendSymbolItem extentItem( mFillSymbol.get(), QStringLiteral( "extent" ), QStringLiteral( "extent" ) );
166  QgsSymbolLegendNode *node = new QgsSymbolLegendNode( nodeLayer, extentItem );
167  node->setEmbeddedInParent( true );
168  nodes << node;
169 
170  return nodes;
171 }
172 
void transformPolygon(QPolygonF &polygon, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transforms a polygon to the destination coordinate system.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1307
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
Layer tree node points to a map layer.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
void transformInPlace(double &x, double &y) const
Transforms device coordinates to map coordinates.
Base class for storing raw data from point cloud nodes.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const override
Saves the renderer configuration to an XML element.
QgsFillSymbol * fillSymbol() const
Returns the symbol used to render the cloud's extent.
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) override
Creates a set of legend nodes representing the renderer.
void startRender(QgsPointCloudRenderContext &context) override
Must be called when a new render cycle is started.
static QgsPointCloudRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates an extent renderer from an XML element.
void stopRender(QgsPointCloudRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
void setFillSymbol(QgsFillSymbol *symbol)
Sets the symbol used to render the cloud's extent.
void renderExtent(const QgsGeometry &extent, QgsPointCloudRenderContext &context)
Renders a polygon extent geometry to the specified render context.
void renderBlock(const QgsPointCloudBlock *block, QgsPointCloudRenderContext &context) override
Renders a block of point cloud data using the specified render context.
static QgsFillSymbol * defaultFillSymbol()
Returns a new instance of the default fill symbol to use for showing point cloud extents.
QgsPointCloudRenderer * clone() const override
Create a deep copy of this renderer.
QString type() const override
Returns the identifier of the renderer type.
QgsPointCloudExtentRenderer(QgsFillSymbol *symbol=nullptr)
Constructor for QgsPointCloudExtentRenderer.
Encapsulates the render context for a 2D point cloud rendering operation.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for 2d point cloud renderers.
void saveCommonProperties(QDomElement &element, const QgsReadWriteContext &context) const
Saves common renderer properties (such as point size and screen error) to the specified DOM element.
void copyCommonProperties(QgsPointCloudRenderer *destination) const
Copies common point cloud properties (such as point size and screen error) to the destination rendere...
virtual void startRender(QgsPointCloudRenderContext &context)
Must be called when a new render cycle is started.
virtual void stopRender(QgsPointCloudRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
Polygon geometry type.
Definition: qgspolygon.h:34
The class is used as a container of context for various read/write operations on other objects.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
void setEmbeddedInParent(bool embedded) override
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition: qgssymbol.h:54