Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[pointclouds] Add an extent only 2d renderer for point clouds
Useful when you just want an overview of the bounds of the layer in a 2d map. Also potentially usable as a temporary renderer for las/laz files while we build the indexed representation of the file in the background.
- Loading branch information
1 parent
6894c85
commit def587f
Showing
19 changed files
with
745 additions
and
18 deletions.
There are no files selected for viewing
89 changes: 89 additions & 0 deletions
89
python/core/auto_generated/pointcloud/qgspointcloudextentrenderer.sip.in
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/core/pointcloud/qgspointcloudextentrenderer.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ | ||
|
||
|
||
|
||
|
||
|
||
class QgsPointCloudExtentRenderer : QgsPointCloudRenderer | ||
{ | ||
%Docstring | ||
A renderer for 2d visualisation of point clouds which shows the dataset's extents using a fill symbol. | ||
|
||
.. versionadded:: 3.18 | ||
%End | ||
|
||
%TypeHeaderCode | ||
#include "qgspointcloudextentrenderer.h" | ||
%End | ||
public: | ||
|
||
QgsPointCloudExtentRenderer( QgsFillSymbol *symbol /Transfer/ = 0 ); | ||
%Docstring | ||
Constructor for QgsPointCloudExtentRenderer. | ||
|
||
Optionally the ``symbol`` to use for showing the extent can be specified. If specified, ownership is | ||
transferred to the renderer. If no ``symbol`` is specified a default one will be created instead. | ||
%End | ||
|
||
virtual QString type() const; | ||
|
||
virtual QgsPointCloudRenderer *clone() const; | ||
|
||
virtual void renderBlock( const QgsPointCloudBlock *block, QgsPointCloudRenderContext &context ); | ||
|
||
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const; | ||
|
||
|
||
virtual void startRender( QgsPointCloudRenderContext &context ); | ||
|
||
virtual void stopRender( QgsPointCloudRenderContext &context ); | ||
|
||
virtual QList<QgsLayerTreeModelLegendNode *> createLegendNodes( QgsLayerTreeLayer *nodeLayer ) /Factory/; | ||
|
||
|
||
static QgsPointCloudRenderer *create( QDomElement &element, const QgsReadWriteContext &context ) /Factory/; | ||
%Docstring | ||
Creates an extent renderer from an XML ``element``. | ||
%End | ||
|
||
void renderExtent( const QgsGeometry &extent, QgsPointCloudRenderContext &context ); | ||
%Docstring | ||
Renders a polygon ``extent`` geometry to the specified render ``context``. | ||
%End | ||
|
||
static QgsFillSymbol *defaultFillSymbol() /Factory/; | ||
%Docstring | ||
Returns a new instance of the default fill symbol to use for showing point cloud extents. | ||
%End | ||
|
||
QgsFillSymbol *fillSymbol() const; | ||
%Docstring | ||
Returns the symbol used to render the cloud's extent. | ||
|
||
.. seealso:: :py:func:`setFillSymbol` | ||
%End | ||
|
||
void setFillSymbol( QgsFillSymbol *symbol /Transfer/ ); | ||
%Docstring | ||
Sets the ``symbol`` used to render the cloud's extent. | ||
|
||
Ownership of ``symbol`` is transferred to the renderer. | ||
|
||
.. seealso:: :py:func:`fillSymbol` | ||
%End | ||
|
||
}; | ||
|
||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/core/pointcloud/qgspointcloudextentrenderer.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/*************************************************************************** | ||
qgspointcloudextentrenderer.h | ||
-------------------- | ||
begin : December 2020 | ||
copyright : (C) 2020 by Nyall Dawson | ||
email : nyall dot dawson at gmail dot com | ||
***************************************************************************/ | ||
|
||
/*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgspointcloudextentrenderer.h" | ||
#include "qgspointcloudblock.h" | ||
#include "qgssymbollayerutils.h" | ||
#include "qgssymbol.h" | ||
#include "qgswkbtypes.h" | ||
#include "qgspolygon.h" | ||
#include "qgscurve.h" | ||
#include "qgslinesymbollayer.h" | ||
#include "qgslayertreemodellegendnode.h" | ||
|
||
QgsPointCloudExtentRenderer::QgsPointCloudExtentRenderer( QgsFillSymbol *symbol ) | ||
: mFillSymbol( symbol ? symbol : defaultFillSymbol() ) | ||
{ | ||
|
||
} | ||
|
||
QString QgsPointCloudExtentRenderer::type() const | ||
{ | ||
return QStringLiteral( "extent" ); | ||
} | ||
|
||
QgsPointCloudRenderer *QgsPointCloudExtentRenderer::clone() const | ||
{ | ||
std::unique_ptr< QgsPointCloudExtentRenderer > res = qgis::make_unique< QgsPointCloudExtentRenderer >( mFillSymbol ? mFillSymbol->clone() : nullptr ); | ||
copyCommonProperties( res.get() ); | ||
return res.release(); | ||
} | ||
|
||
void QgsPointCloudExtentRenderer::renderBlock( const QgsPointCloudBlock *, QgsPointCloudRenderContext & ) | ||
{ | ||
|
||
} | ||
|
||
QgsPointCloudRenderer *QgsPointCloudExtentRenderer::create( QDomElement &element, const QgsReadWriteContext &context ) | ||
{ | ||
std::unique_ptr< QgsPointCloudExtentRenderer > r = qgis::make_unique< QgsPointCloudExtentRenderer >(); | ||
|
||
QDomElement symbolElem = element.firstChildElement( QStringLiteral( "symbol" ) ); | ||
if ( !symbolElem.isNull() ) | ||
{ | ||
r->mFillSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( symbolElem, context ) ); | ||
} | ||
|
||
r->restoreCommonProperties( element, context ); | ||
return r.release(); | ||
} | ||
|
||
void QgsPointCloudExtentRenderer::renderExtent( const QgsGeometry &extent, QgsPointCloudRenderContext &context ) | ||
{ | ||
auto transformRing = [&context]( QPolygonF & pts ) | ||
{ | ||
//transform the QPolygonF to screen coordinates | ||
if ( context.renderContext().coordinateTransform().isValid() ) | ||
{ | ||
try | ||
{ | ||
context.renderContext().coordinateTransform().transformPolygon( pts ); | ||
} | ||
catch ( QgsCsException & ) | ||
{ | ||
// we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid | ||
} | ||
} | ||
|
||
// remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors | ||
pts.erase( std::remove_if( pts.begin(), pts.end(), | ||
[]( const QPointF point ) | ||
{ | ||
return !std::isfinite( point.x() ) || !std::isfinite( point.y() ); | ||
} ), pts.end() ); | ||
|
||
QPointF *ptr = pts.data(); | ||
for ( int i = 0; i < pts.size(); ++i, ++ptr ) | ||
{ | ||
context.renderContext().mapToPixel().transformInPlace( ptr->rx(), ptr->ry() ); | ||
} | ||
}; | ||
|
||
for ( auto it = extent.const_parts_begin(); it != extent.const_parts_end(); ++it ) | ||
{ | ||
if ( const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( *it ) ) | ||
{ | ||
QPolygonF exterior = polygon->exteriorRing()->asQPolygonF(); | ||
transformRing( exterior ); | ||
QVector<QPolygonF> rings; | ||
rings.reserve( polygon->numInteriorRings() ); | ||
for ( int i = 0; i < polygon->numInteriorRings(); ++i ) | ||
{ | ||
QPolygonF ring = polygon->interiorRing( i )->asQPolygonF(); | ||
transformRing( ring ); | ||
rings.append( ring ); | ||
} | ||
|
||
mFillSymbol->renderPolygon( exterior, rings.empty() ? nullptr : &rings, nullptr, context.renderContext() ); | ||
} | ||
} | ||
} | ||
|
||
QgsFillSymbol *QgsPointCloudExtentRenderer::defaultFillSymbol() | ||
{ | ||
std::unique_ptr< QgsSimpleLineSymbolLayer > layer = qgis::make_unique< QgsSimpleLineSymbolLayer >(); | ||
layer->setColor( QColor( 228, 26, 28 ) ); | ||
layer->setWidth( 0.960000 ); | ||
layer->setPenStyle( Qt::DotLine ); | ||
layer->setWidthUnit( QgsUnitTypes::RenderMillimeters ); | ||
return new QgsFillSymbol( QgsSymbolLayerList() << layer.release() ); | ||
} | ||
|
||
QgsFillSymbol *QgsPointCloudExtentRenderer::fillSymbol() const | ||
{ | ||
return mFillSymbol.get(); | ||
} | ||
|
||
void QgsPointCloudExtentRenderer::setFillSymbol( QgsFillSymbol *symbol ) | ||
{ | ||
mFillSymbol.reset( symbol ); | ||
} | ||
|
||
QDomElement QgsPointCloudExtentRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context ) const | ||
{ | ||
QDomElement rendererElem = doc.createElement( QStringLiteral( "renderer" ) ); | ||
|
||
rendererElem.setAttribute( QStringLiteral( "type" ), type() ); | ||
|
||
QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QString(), mFillSymbol.get(), doc, context ); | ||
rendererElem.appendChild( symbolElem ); | ||
|
||
saveCommonProperties( rendererElem, context ); | ||
return rendererElem; | ||
} | ||
|
||
void QgsPointCloudExtentRenderer::startRender( QgsPointCloudRenderContext &context ) | ||
{ | ||
QgsPointCloudRenderer::startRender( context ); | ||
mFillSymbol->startRender( context.renderContext() ); | ||
} | ||
|
||
void QgsPointCloudExtentRenderer::stopRender( QgsPointCloudRenderContext &context ) | ||
{ | ||
QgsPointCloudRenderer::stopRender( context ); | ||
mFillSymbol->stopRender( context.renderContext() ); | ||
} | ||
|
||
QList<QgsLayerTreeModelLegendNode *> QgsPointCloudExtentRenderer::createLegendNodes( QgsLayerTreeLayer *nodeLayer ) | ||
{ | ||
QList<QgsLayerTreeModelLegendNode *> nodes; | ||
|
||
QgsLegendSymbolItem extentItem( mFillSymbol.get(), QStringLiteral( "extent" ), QStringLiteral( "extent" ) ); | ||
QgsSymbolLegendNode *node = new QgsSymbolLegendNode( nodeLayer, extentItem ); | ||
node->setEmbeddedInParent( true ); | ||
nodes << node; | ||
|
||
return nodes; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/*************************************************************************** | ||
qgspointcloudextentrenderer.h | ||
-------------------- | ||
begin : December 2020 | ||
copyright : (C) 2020 by Nyall Dawson | ||
email : nyall dot dawson at gmail dot com | ||
***************************************************************************/ | ||
|
||
/*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSPOINTCLOUDEXTENTRENDERER_H | ||
#define QGSPOINTCLOUDEXTENTRENDERER_H | ||
|
||
#include "qgspointcloudrenderer.h" | ||
#include "qgis_core.h" | ||
#include "qgis_sip.h" | ||
|
||
class QgsFillSymbol; | ||
|
||
/** | ||
* \ingroup core | ||
* A renderer for 2d visualisation of point clouds which shows the dataset's extents using a fill symbol. | ||
* | ||
* \since QGIS 3.18 | ||
*/ | ||
class CORE_EXPORT QgsPointCloudExtentRenderer : public QgsPointCloudRenderer | ||
{ | ||
public: | ||
|
||
/** | ||
* Constructor for QgsPointCloudExtentRenderer. | ||
* | ||
* Optionally the \a symbol to use for showing the extent can be specified. If specified, ownership is | ||
* transferred to the renderer. If no \a symbol is specified a default one will be created instead. | ||
*/ | ||
QgsPointCloudExtentRenderer( QgsFillSymbol *symbol SIP_TRANSFER = nullptr ); | ||
|
||
QString type() const override; | ||
QgsPointCloudRenderer *clone() const override; | ||
void renderBlock( const QgsPointCloudBlock *block, QgsPointCloudRenderContext &context ) override; | ||
QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const override; | ||
|
||
void startRender( QgsPointCloudRenderContext &context ) override; | ||
void stopRender( QgsPointCloudRenderContext &context ) override; | ||
QList<QgsLayerTreeModelLegendNode *> createLegendNodes( QgsLayerTreeLayer *nodeLayer ) override SIP_FACTORY; | ||
|
||
/** | ||
* Creates an extent renderer from an XML \a element. | ||
*/ | ||
static QgsPointCloudRenderer *create( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY; | ||
|
||
/** | ||
* Renders a polygon \a extent geometry to the specified render \a context. | ||
*/ | ||
void renderExtent( const QgsGeometry &extent, QgsPointCloudRenderContext &context ); | ||
|
||
/** | ||
* Returns a new instance of the default fill symbol to use for showing point cloud extents. | ||
*/ | ||
static QgsFillSymbol *defaultFillSymbol() SIP_FACTORY; | ||
|
||
/** | ||
* Returns the symbol used to render the cloud's extent. | ||
* | ||
* \see setFillSymbol() | ||
*/ | ||
QgsFillSymbol *fillSymbol() const; | ||
|
||
/** | ||
* Sets the \a symbol used to render the cloud's extent. | ||
* | ||
* Ownership of \a symbol is transferred to the renderer. | ||
* | ||
* \see fillSymbol() | ||
*/ | ||
void setFillSymbol( QgsFillSymbol *symbol SIP_TRANSFER ); | ||
|
||
private: | ||
|
||
std::unique_ptr< QgsFillSymbol > mFillSymbol; | ||
|
||
}; | ||
|
||
#endif // QGSPOINTCLOUDEXTENTRENDERER_H |
Oops, something went wrong.