Skip to content
Permalink
Browse files

Move some common code to base class

  • Loading branch information
nyalldawson committed Nov 12, 2020
1 parent 3ca572c commit 948a7dc9bc12c3206c44b7493d4016a121d156ed
@@ -63,6 +63,39 @@ Increments the count of points rendered by the specified amount.

It is a point cloud renderer's responsibility to correctly call this after
rendering a block of points.
%End

QgsPointCloudAttributeCollection attributes() const;
%Docstring
Returns the attributes associated with the rendered block.

.. seealso:: :py:func:`setAttributes`
%End

void setAttributes( const QgsPointCloudAttributeCollection &attributes );
%Docstring
Sets the ``attributes`` associated with the rendered block.

.. seealso:: :py:func:`attributes`
%End

int pointRecordSize() const;
%Docstring
Returns the size of a single point record.
%End

int xOffset() const;
%Docstring
Returns the offset for the x value in a point record.

.. seealso:: :py:func:`yOffset`
%End

int yOffset() const;
%Docstring
Returns the offset for the y value in a point record.

.. seealso:: :py:func:`xOffset`
%End

private:
@@ -102,6 +135,11 @@ Caller takes ownership of the returned renderer.

virtual ~QgsPointCloudRenderer();

virtual QString type() const = 0;
%Docstring
Returns the identifier of the renderer type.
%End

virtual QgsPointCloudRenderer *clone() const = 0 /Factory/;
%Docstring
Create a deep copy of this renderer. Should be implemented by all subclasses
@@ -165,6 +203,13 @@ Calls to :py:func:`~QgsPointCloudRenderer.stopRender` must always be preceded by
the renderer should instead be cloned and :py:func:`~QgsPointCloudRenderer.startRender`/:py:func:`~QgsPointCloudRenderer.stopRender` called on the clone.

.. seealso:: :py:func:`startRender`
%End

protected:

static void pointXY( QgsPointCloudRenderContext &context, const char *ptr, int i, double &x, double &y );
%Docstring
Retrieves the x and y coordinate for the point at index ``i``.
%End

};
@@ -26,6 +26,7 @@ An RGB renderer for 2d visualisation of point clouds using embedded red, green a
%Docstring
Constructor for QgsPointCloudRgbRenderer.
%End
virtual QString type() const;

virtual QgsPointCloudRenderer *clone() const;

@@ -102,6 +102,9 @@ bool QgsPointCloudLayerRenderer::render()
float rootErrorPixels = rootError / mapUnitsPerPixel; // in pixels
const QList<IndexedPointCloudNode> nodes = traverseTree( pc, context.renderContext(), pc->root(), maximumError, rootErrorPixels );

QgsPointCloudRequest request;
request.setAttributes( mAttributes );

// drawing
int nodesDrawn = 0;
for ( const IndexedPointCloudNode &n : nodes )
@@ -111,13 +114,13 @@ bool QgsPointCloudLayerRenderer::render()
qDebug() << "canceled";
break;
}
QgsPointCloudRequest request;
request.setAttributes( mAttributes );
std::unique_ptr<QgsPointCloudBlock> block( pc->nodeData( n, request ) );

if ( !block )
continue;

context.setAttributes( block->attributes() );

mRenderer->renderBlock( block.get(), context );
++nodesDrawn;
}
@@ -37,6 +37,16 @@ void QgsPointCloudRenderContext::incrementPointsRendered( long count )
mPointsRendered += count;
}

void QgsPointCloudRenderContext::setAttributes( const QgsPointCloudAttributeCollection &attributes )
{
mAttributes = attributes;
mPointRecordSize = mAttributes.pointRecordSize();

// fetch offset for x/y attributes
attributes.find( QStringLiteral( "X" ), mXOffset );
attributes.find( QStringLiteral( "Y" ), mYOffset );
}

QgsPointCloudRenderer *QgsPointCloudRenderer::defaultRenderer()
{
return new QgsDummyPointCloudRenderer();
@@ -85,6 +95,8 @@ void QgsPointCloudRenderer::stopRender( QgsPointCloudRenderContext & )
}




#include "qgscolorramp.h"
#include "qgspointcloudblock.h"
#include "qgsstyle.h"
@@ -125,33 +137,21 @@ void QgsDummyPointCloudRenderer::renderBlock( const QgsPointCloudBlock *block, Q
const QgsPointCloudAttributeCollection request = block->attributes();
const std::size_t recordSize = request.pointRecordSize();

int xOffset = 0;
const QgsPointCloudAttribute *attribute = request.find( QStringLiteral( "X" ), xOffset );
if ( !attribute )
return;

int yOffset = 0;
attribute = request.find( QStringLiteral( "Y" ), yOffset );
if ( !attribute )
return;

int attributeOffset = 0;
attribute = request.find( mAttribute, attributeOffset );
const QgsPointCloudAttribute *attribute = request.find( mAttribute, attributeOffset );
if ( !attribute )
return;

const QgsPointCloudAttribute::DataType type = attribute->type();
const bool applyZOffset = attribute->name() == QLatin1String( "Z" );

int rendered = 0;
double x = 0;
double y = 0;
for ( int i = 0; i < count; ++i )
{
// TODO clean up!
qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
pointXY( context, ptr, i, x, y );

double x = offset.x() + scale.x() * ix;
double y = offset.y() + scale.y() * iy;
if ( mapExtent.contains( QgsPointXY( x, y ) ) )
{
double atr = 0;
@@ -23,6 +23,7 @@
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsvector3d.h"
#include "qgspointcloudattribute.h"

class QgsPointCloudBlock;

@@ -87,6 +88,39 @@ class CORE_EXPORT QgsPointCloudRenderContext
*/
void incrementPointsRendered( long count );

/**
* Returns the attributes associated with the rendered block.
*
* \see setAttributes()
*/
QgsPointCloudAttributeCollection attributes() const { return mAttributes; }

/**
* Sets the \a attributes associated with the rendered block.
*
* \see attributes()
*/
void setAttributes( const QgsPointCloudAttributeCollection &attributes );

/**
* Returns the size of a single point record.
*/
int pointRecordSize() const { return mPointRecordSize; }

/**
* Returns the offset for the x value in a point record.
*
* \see yOffset()
*/
int xOffset() const { return mXOffset; }

/**
* Returns the offset for the y value in a point record.
*
* \see xOffset()
*/
int yOffset() const { return mYOffset; }

private:
#ifdef SIP_RUN
QgsPointCloudRenderContext( const QgsPointCloudRenderContext &rh );
@@ -96,6 +130,10 @@ class CORE_EXPORT QgsPointCloudRenderContext
QgsVector3D mScale;
QgsVector3D mOffset;
long mPointsRendered = 0;
QgsPointCloudAttributeCollection mAttributes;
int mPointRecordSize = 0;
int mXOffset = 0;
int mYOffset = 0;
};


@@ -133,6 +171,11 @@ class CORE_EXPORT QgsPointCloudRenderer

virtual ~QgsPointCloudRenderer() = default;

/**
* Returns the identifier of the renderer type.
*/
virtual QString type() const = 0;

/**
* Create a deep copy of this renderer. Should be implemented by all subclasses
* and generate a proper subclass.
@@ -191,6 +234,20 @@ class CORE_EXPORT QgsPointCloudRenderer
*/
virtual void stopRender( QgsPointCloudRenderContext &context );

protected:

/**
* Retrieves the x and y coordinate for the point at index \a i.
*/
static void pointXY( QgsPointCloudRenderContext &context, const char *ptr, int i, double &x, double &y )
{
qint32 ix = *( qint32 * )( ptr + i * context.pointRecordSize() + context.xOffset() );
qint32 iy = *( qint32 * )( ptr + i * context.pointRecordSize() + context.yOffset() );

x = context.offset().x() + context.scale().x() * ix;
y = context.offset().y() + context.scale().y() * iy;
}

private:
#ifdef QGISDEBUG
//! Pointer to thread in which startRender was first called
@@ -215,6 +272,8 @@ class CORE_EXPORT QgsDummyPointCloudRenderer : public QgsPointCloudRenderer
void stopRender( QgsPointCloudRenderContext &context ) override;
QSet< QString > usedAttributes( const QgsPointCloudRenderContext &context ) const override;

QString type() const override { return QStringLiteral( "dummy" ); }

/**
* Creates a dummy renderer from an XML \a element.
*/
@@ -23,6 +23,11 @@ QgsPointCloudRgbRenderer::QgsPointCloudRgbRenderer()

}

QString QgsPointCloudRgbRenderer::type() const
{
return QStringLiteral( "rgb" );
}

QgsPointCloudRenderer *QgsPointCloudRgbRenderer::clone() const
{
std::unique_ptr< QgsPointCloudRgbRenderer > res = qgis::make_unique< QgsPointCloudRgbRenderer >();
@@ -36,8 +41,6 @@ QgsPointCloudRenderer *QgsPointCloudRgbRenderer::clone() const
void QgsPointCloudRgbRenderer::renderBlock( const QgsPointCloudBlock *block, QgsPointCloudRenderContext &context )
{
const QgsMapToPixel mapToPixel = context.renderContext().mapToPixel();
const QgsVector3D scale = context.scale();
const QgsVector3D offset = context.offset();

QgsRectangle mapExtent = context.renderContext().mapExtent();

@@ -49,20 +52,10 @@ void QgsPointCloudRgbRenderer::renderBlock( const QgsPointCloudBlock *block, Qgs
const char *ptr = block->data();
int count = block->pointCount();
const QgsPointCloudAttributeCollection request = block->attributes();
const std::size_t recordSize = request.pointRecordSize();

int xOffset = 0;
const QgsPointCloudAttribute *attribute = request.find( QStringLiteral( "X" ), xOffset );
if ( !attribute )
return;

int yOffset = 0;
attribute = request.find( QStringLiteral( "Y" ), yOffset );
if ( !attribute )
return;

const std::size_t recordSize = request.pointRecordSize();
int redOffset = 0;
attribute = request.find( mRedAttribute, redOffset );
const QgsPointCloudAttribute *attribute = request.find( mRedAttribute, redOffset );
if ( !attribute )
return;
const QgsPointCloudAttribute::DataType redType = attribute->type();
@@ -80,14 +73,12 @@ void QgsPointCloudRgbRenderer::renderBlock( const QgsPointCloudBlock *block, Qgs
const QgsPointCloudAttribute::DataType blueType = attribute->type();

int rendered = 0;
double x = 0;
double y = 0;
for ( int i = 0; i < count; ++i )
{
// TODO move some of this to base class!
qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
pointXY( context, ptr, i, x, y );

double x = offset.x() + scale.x() * ix;
double y = offset.y() + scale.y() * iy;
if ( mapExtent.contains( QgsPointXY( x, y ) ) )
{
int red = 0;
@@ -36,7 +36,7 @@ class CORE_EXPORT QgsPointCloudRgbRenderer : public QgsPointCloudRenderer
* Constructor for QgsPointCloudRgbRenderer.
*/
QgsPointCloudRgbRenderer();

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;
@@ -28,6 +28,7 @@ class DummyRenderer : public QgsPointCloudRenderer
{
public:
DummyRenderer() = default;
QString type() const override { return QStringLiteral( "dummy" ); }
QgsPointCloudRenderer *clone() const override { return new DummyRenderer(); }
static QgsPointCloudRenderer *create( QDomElement &, const QgsReadWriteContext & ) { return new DummyRenderer(); }
void renderBlock( const QgsPointCloudBlock *, QgsPointCloudRenderContext & ) override {}

0 comments on commit 948a7dc

Please sign in to comment.
You can’t perform that action at this time.