Skip to content

Commit

Permalink
[pointclouds] Add an elevation tab in layer properties, and allow
Browse files Browse the repository at this point in the history
users to set a manual offset to apply to point cloud z values

This allows for adjustment of the elevation of point clouds, eg so that:
1. They match nicely with point clouds from other datasources
2. Users can use point clouds from sources with arbitrary z values,
eg. a point cloud made by opendronemap without any actual reference
z values available
  • Loading branch information
nyalldawson committed Dec 16, 2020
1 parent 9eea646 commit 1963ef9
Show file tree
Hide file tree
Showing 16 changed files with 233 additions and 33 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -38,6 +38,27 @@ Constructor for QgsPointCloudLayerElevationProperties, with the specified ``pare


virtual QgsDoubleRange calculateZRange( QgsMapLayer *layer ) const; virtual QgsDoubleRange calculateZRange( QgsMapLayer *layer ) const;



double zOffset() const;
%Docstring
Returns the z offset, which is a fixed offset amount which should be added to z values from
the layer.

This can be used to correct or manually adjust for incorrect elevation values in a point cloud layer.

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

void setZOffset( double offset );
%Docstring
Sets the z ``offset``, which is a fixed offset amount which will be added to z values from
the layer.

This can be used to correct or manually adjust for incorrect elevation values in a point cloud layer.

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

}; };


/************************************************************************ /************************************************************************
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ Encapsulates the render context for a 2D point cloud rendering operation.
%End %End
public: public:


QgsPointCloudRenderContext( QgsRenderContext &context, const QgsVector3D &scale, const QgsVector3D &offset ); QgsPointCloudRenderContext( QgsRenderContext &context, const QgsVector3D &scale, const QgsVector3D &offset,
double zValueFixedOffset );
%Docstring %Docstring
Constructor for QgsPointCloudRenderContext. Constructor for QgsPointCloudRenderContext.


The ``scale`` and ``offset`` arguments specify the scale and offset of the layer's int32 coordinates The ``scale`` and ``offset`` arguments specify the scale and offset of the layer's int32 coordinates
compared to CRS coordinates respectively. compared to CRS coordinates respectively.

The ``zValueFixedOffset`` argument specifies any constant offset value which must be added to z values
taken from the point cloud index.
%End %End




Expand Down Expand Up @@ -110,6 +114,11 @@ Returns the offset for the y value in a point record.
.. seealso:: :py:func:`yOffset` .. seealso:: :py:func:`yOffset`
%End %End


double zValueFixedOffset() const;
%Docstring
Returns any constant offset which must be applied to z values taken from the point cloud index.
%End



private: private:
QgsPointCloudRenderContext( const QgsPointCloudRenderContext &rh ); QgsPointCloudRenderContext( const QgsPointCloudRenderContext &rh );
Expand Down
7 changes: 5 additions & 2 deletions src/3d/qgspointcloudlayer3drenderer.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
#include "qgsapplication.h" #include "qgsapplication.h"
#include "qgs3dsymbolregistry.h" #include "qgs3dsymbolregistry.h"
#include "qgspointcloud3dsymbol.h" #include "qgspointcloud3dsymbol.h"
#include "qgspointcloudlayerelevationproperties.h"


#include "qgis.h" #include "qgis.h"


QgsPointCloud3DRenderContext::QgsPointCloud3DRenderContext( const Qgs3DMapSettings &map, std::unique_ptr<QgsPointCloud3DSymbol> symbol ) QgsPointCloud3DRenderContext::QgsPointCloud3DRenderContext( const Qgs3DMapSettings &map, std::unique_ptr<QgsPointCloud3DSymbol> symbol, double zValueFixedOffset )
: Qgs3DRenderContext( map ) : Qgs3DRenderContext( map )
, mSymbol( std::move( symbol ) ) , mSymbol( std::move( symbol ) )
, mZValueFixedOffset( zValueFixedOffset )
{ {


} }
Expand Down Expand Up @@ -112,7 +114,8 @@ Qt3DCore::QEntity *QgsPointCloudLayer3DRenderer::createEntity( const Qgs3DMapSet
if ( !mSymbol ) if ( !mSymbol )
return nullptr; return nullptr;


return new QgsPointCloudLayerChunkedEntity( pcl->dataProvider()->index(), map, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ), maximumScreenError(), showBoundingBoxes() ); return new QgsPointCloudLayerChunkedEntity( pcl->dataProvider()->index(), map, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ), maximumScreenError(), showBoundingBoxes(),
static_cast< const QgsPointCloudLayerElevationProperties * >( pcl->elevationProperties() )->zOffset() );
} }


void QgsPointCloudLayer3DRenderer::setSymbol( QgsPointCloud3DSymbol *symbol ) void QgsPointCloudLayer3DRenderer::setSymbol( QgsPointCloud3DSymbol *symbol )
Expand Down
16 changes: 14 additions & 2 deletions src/3d/qgspointcloudlayer3drenderer.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -43,8 +43,14 @@ class _3D_NO_EXPORT QgsPointCloud3DRenderContext : public Qgs3DRenderContext
{ {
public: public:


//! Constructor for QgsPointCloud3DRenderContext. /**
QgsPointCloud3DRenderContext( const Qgs3DMapSettings &map, std::unique_ptr< QgsPointCloud3DSymbol > symbol ); * Constructor for QgsPointCloud3DRenderContext.
*
* The \a zValueFixedOffset argument specifies any constant offset value which must be added to z values
* taken from the point cloud index.
*/
QgsPointCloud3DRenderContext( const Qgs3DMapSettings &map, std::unique_ptr< QgsPointCloud3DSymbol > symbol,
double zValueFixedOffset );


//! QgsPointCloudRenderContext cannot be copied. //! QgsPointCloudRenderContext cannot be copied.
QgsPointCloud3DRenderContext( const QgsPointCloud3DRenderContext &rh ) = delete; QgsPointCloud3DRenderContext( const QgsPointCloud3DRenderContext &rh ) = delete;
Expand Down Expand Up @@ -127,13 +133,19 @@ class _3D_NO_EXPORT QgsPointCloud3DRenderContext : public Qgs3DRenderContext
} }
} }


/**
* Returns any constant offset which must be applied to z values taken from the point cloud index.
*/
double zValueFixedOffset() const { return mZValueFixedOffset; }

private: private:
#ifdef SIP_RUN #ifdef SIP_RUN
QgsPointCloudRenderContext( const QgsPointCloudRenderContext &rh ); QgsPointCloudRenderContext( const QgsPointCloudRenderContext &rh );
#endif #endif
QgsPointCloudAttributeCollection mAttributes; QgsPointCloudAttributeCollection mAttributes;
std::unique_ptr<QgsPointCloud3DSymbol> mSymbol; std::unique_ptr<QgsPointCloud3DSymbol> mSymbol;
QgsPointCloudCategoryList mFilteredOutCategories; QgsPointCloudCategoryList mFilteredOutCategories;
double mZValueFixedOffset = 0;
}; };




Expand Down
23 changes: 12 additions & 11 deletions src/3d/qgspointcloudlayerchunkloader_p.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@


/////////////// ///////////////


QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node, std::unique_ptr< QgsPointCloud3DSymbol > symbol ) QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node, std::unique_ptr< QgsPointCloud3DSymbol > symbol, double zValueOffset )
: QgsChunkLoader( node ) : QgsChunkLoader( node )
, mFactory( factory ) , mFactory( factory )
, mContext( factory->mMap, std::move( symbol ) ) , mContext( factory->mMap, std::move( symbol ), zValueOffset )
{ {
QgsPointCloudIndex *pc = mFactory->mPointCloudIndex; QgsPointCloudIndex *pc = mFactory->mPointCloudIndex;
mContext.setAttributes( pc->attributes() ); mContext.setAttributes( pc->attributes() );
Expand Down Expand Up @@ -126,9 +126,10 @@ Qt3DCore::QEntity *QgsPointCloudLayerChunkLoader::createEntity( Qt3DCore::QEntit
/////////////// ///////////////




QgsPointCloudLayerChunkLoaderFactory::QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol ) QgsPointCloudLayerChunkLoaderFactory::QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol, double zValueOffset )
: mMap( map ) : mMap( map )
, mPointCloudIndex( pc ) , mPointCloudIndex( pc )
, mZValueOffset( zValueOffset )
{ {
mSymbol.reset( symbol ); mSymbol.reset( symbol );
} }
Expand All @@ -137,14 +138,14 @@ QgsChunkLoader *QgsPointCloudLayerChunkLoaderFactory::createChunkLoader( QgsChun
{ {
QgsChunkNodeId id = node->tileId(); QgsChunkNodeId id = node->tileId();
Q_ASSERT( mPointCloudIndex->hasNode( IndexedPointCloudNode( id.d, id.x, id.y, id.z ) ) ); Q_ASSERT( mPointCloudIndex->hasNode( IndexedPointCloudNode( id.d, id.x, id.y, id.z ) ) );
return new QgsPointCloudLayerChunkLoader( this, node, std::unique_ptr< QgsPointCloud3DSymbol >( static_cast< QgsPointCloud3DSymbol * >( mSymbol->clone() ) ) ); return new QgsPointCloudLayerChunkLoader( this, node, std::unique_ptr< QgsPointCloud3DSymbol >( static_cast< QgsPointCloud3DSymbol * >( mSymbol->clone() ) ), mZValueOffset );
} }


QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DMapSettings &map ); QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DMapSettings &map, double zValueOffset );


QgsChunkNode *QgsPointCloudLayerChunkLoaderFactory::createRootNode() const QgsChunkNode *QgsPointCloudLayerChunkLoaderFactory::createRootNode() const
{ {
QgsAABB bbox = nodeBoundsToAABB( mPointCloudIndex->nodeBounds( IndexedPointCloudNode( 0, 0, 0, 0 ) ), mPointCloudIndex->offset(), mPointCloudIndex->scale(), mMap ); QgsAABB bbox = nodeBoundsToAABB( mPointCloudIndex->nodeBounds( IndexedPointCloudNode( 0, 0, 0, 0 ) ), mPointCloudIndex->offset(), mPointCloudIndex->scale(), mMap, mZValueOffset );
float error = mPointCloudIndex->nodeError( IndexedPointCloudNode( 0, 0, 0, 0 ) ); float error = mPointCloudIndex->nodeError( IndexedPointCloudNode( 0, 0, 0, 0 ) );
return new QgsChunkNode( QgsChunkNodeId( 0, 0, 0, 0 ), bbox, error ); return new QgsChunkNode( QgsChunkNodeId( 0, 0, 0, 0 ), bbox, error );
} }
Expand Down Expand Up @@ -183,11 +184,11 @@ QVector<QgsChunkNode *> QgsPointCloudLayerChunkLoaderFactory::createChildren( Qg
/////////////// ///////////////




QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DMapSettings &map ) QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DMapSettings &map, double zValueOffset )
{ {
// TODO: reprojection from layer to map coordinates if needed // TODO: reprojection from layer to map coordinates if needed
QgsVector3D extentMin3D( nodeBounds.xMin() * scale.x() + offset.x(), nodeBounds.yMin() * scale.y() + offset.y(), nodeBounds.zMin() * scale.z() + offset.z() ); QgsVector3D extentMin3D( nodeBounds.xMin() * scale.x() + offset.x(), nodeBounds.yMin() * scale.y() + offset.y(), nodeBounds.zMin() * scale.z() + offset.z() + zValueOffset );
QgsVector3D extentMax3D( nodeBounds.xMax() * scale.x() + offset.x(), nodeBounds.yMax() * scale.y() + offset.y(), nodeBounds.zMax() * scale.z() + offset.z() ); QgsVector3D extentMax3D( nodeBounds.xMax() * scale.x() + offset.x(), nodeBounds.yMax() * scale.y() + offset.y(), nodeBounds.zMax() * scale.z() + offset.z() + zValueOffset );
QgsVector3D worldExtentMin3D = Qgs3DUtils::mapToWorldCoordinates( extentMin3D, map.origin() ); QgsVector3D worldExtentMin3D = Qgs3DUtils::mapToWorldCoordinates( extentMin3D, map.origin() );
QgsVector3D worldExtentMax3D = Qgs3DUtils::mapToWorldCoordinates( extentMax3D, map.origin() ); QgsVector3D worldExtentMax3D = Qgs3DUtils::mapToWorldCoordinates( extentMax3D, map.origin() );
QgsAABB rootBbox( worldExtentMin3D.x(), worldExtentMin3D.y(), worldExtentMin3D.z(), QgsAABB rootBbox( worldExtentMin3D.x(), worldExtentMin3D.y(), worldExtentMin3D.z(),
Expand All @@ -196,9 +197,9 @@ QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset
} }




QgsPointCloudLayerChunkedEntity::QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map, QgsPointCloud3DSymbol *symbol, float maxScreenError, bool showBoundingBoxes ) QgsPointCloudLayerChunkedEntity::QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map, QgsPointCloud3DSymbol *symbol, float maxScreenError, bool showBoundingBoxes, double zValueOffset )
: QgsChunkedEntity( maxScreenError, : QgsChunkedEntity( maxScreenError,
new QgsPointCloudLayerChunkLoaderFactory( map, pc, symbol ), true ) new QgsPointCloudLayerChunkLoaderFactory( map, pc, symbol, zValueOffset ), true )
{ {
setUsingAdditiveStrategy( true ); setUsingAdditiveStrategy( true );
setShowBoundingBoxes( showBoundingBoxes ); setShowBoundingBoxes( showBoundingBoxes );
Expand Down
8 changes: 5 additions & 3 deletions src/3d/qgspointcloudlayerchunkloader_p.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class QgsPointCloudLayerChunkLoaderFactory : public QgsChunkLoaderFactory
* Constructs the factory * Constructs the factory
* The factory takes ownership over the passed \a symbol * The factory takes ownership over the passed \a symbol
*/ */
QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol ); QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol, double zValueOffset );


//! Creates loader for the given chunk node. Ownership of the returned is passed to the caller. //! Creates loader for the given chunk node. Ownership of the returned is passed to the caller.
virtual QgsChunkLoader *createChunkLoader( QgsChunkNode *node ) const override; virtual QgsChunkLoader *createChunkLoader( QgsChunkNode *node ) const override;
Expand All @@ -67,6 +67,7 @@ class QgsPointCloudLayerChunkLoaderFactory : public QgsChunkLoaderFactory
const Qgs3DMapSettings &mMap; const Qgs3DMapSettings &mMap;
QgsPointCloudIndex *mPointCloudIndex; QgsPointCloudIndex *mPointCloudIndex;
std::unique_ptr< QgsPointCloud3DSymbol > mSymbol; std::unique_ptr< QgsPointCloud3DSymbol > mSymbol;
double mZValueOffset = 0;
}; };




Expand All @@ -86,7 +87,7 @@ class QgsPointCloudLayerChunkLoader : public QgsChunkLoader
* Constructs the loader * Constructs the loader
* QgsPointCloudLayerChunkLoader takes ownership over symbol * QgsPointCloudLayerChunkLoader takes ownership over symbol
*/ */
QgsPointCloudLayerChunkLoader( const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node, std::unique_ptr< QgsPointCloud3DSymbol > symbol ); QgsPointCloudLayerChunkLoader( const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node, std::unique_ptr< QgsPointCloud3DSymbol > symbol, double zValueOffset );
~QgsPointCloudLayerChunkLoader() override; ~QgsPointCloudLayerChunkLoader() override;


virtual void cancel() override; virtual void cancel() override;
Expand Down Expand Up @@ -115,7 +116,8 @@ class QgsPointCloudLayerChunkedEntity : public QgsChunkedEntity
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map, QgsPointCloud3DSymbol *symbol, float maxScreenError, bool showBoundingBoxes ); explicit QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map, QgsPointCloud3DSymbol *symbol, float maxScreenError, bool showBoundingBoxes,
double zValueOffset );


~QgsPointCloudLayerChunkedEntity(); ~QgsPointCloudLayerChunkedEntity();
}; };
Expand Down
13 changes: 9 additions & 4 deletions src/3d/symbols/qgspointcloud3dsymbol_p.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ void QgsSingleColorPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *p


const QgsVector3D scale = pc->scale(); const QgsVector3D scale = pc->scale();
const QgsVector3D offset = pc->offset(); const QgsVector3D offset = pc->offset();
const double zValueOffset = context.zValueFixedOffset();


for ( int i = 0; i < count; ++i ) for ( int i = 0; i < count; ++i )
{ {
Expand All @@ -269,7 +270,7 @@ void QgsSingleColorPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *p


double x = offset.x() + scale.x() * ix; double x = offset.x() + scale.x() * ix;
double y = offset.y() + scale.y() * iy; double y = offset.y() + scale.y() * iy;
double z = offset.z() + scale.z() * iz; double z = offset.z() + scale.z() * iz + zValueOffset;
QgsVector3D point( x, y, z ); QgsVector3D point( x, y, z );
QgsVector3D p = context.map().mapToWorldCoordinates( point ); QgsVector3D p = context.map().mapToWorldCoordinates( point );
outNormal.positions.push_back( QVector3D( p.x(), p.y(), p.z() ) ); outNormal.positions.push_back( QVector3D( p.x(), p.y(), p.z() ) );
Expand Down Expand Up @@ -314,6 +315,7 @@ void QgsColorRampPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc,
bool attrIsZ = false; bool attrIsZ = false;
QgsPointCloudAttribute::DataType attributeType = QgsPointCloudAttribute::Float; QgsPointCloudAttribute::DataType attributeType = QgsPointCloudAttribute::Float;
int attributeOffset = 0; int attributeOffset = 0;
const double zValueOffset = context.zValueFixedOffset();
QgsColorRampPointCloud3DSymbol *symbol = dynamic_cast<QgsColorRampPointCloud3DSymbol *>( context.symbol() ); QgsColorRampPointCloud3DSymbol *symbol = dynamic_cast<QgsColorRampPointCloud3DSymbol *>( context.symbol() );
if ( symbol ) if ( symbol )
{ {
Expand Down Expand Up @@ -369,7 +371,7 @@ void QgsColorRampPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc,


double x = offset.x() + scale.x() * ix; double x = offset.x() + scale.x() * ix;
double y = offset.y() + scale.y() * iy; double y = offset.y() + scale.y() * iy;
double z = offset.z() + scale.z() * iz; double z = offset.z() + scale.z() * iz + zValueOffset;
QgsVector3D point( x, y, z ); QgsVector3D point( x, y, z );


QgsVector3D p = context.map().mapToWorldCoordinates( point ); QgsVector3D p = context.map().mapToWorldCoordinates( point );
Expand Down Expand Up @@ -451,6 +453,7 @@ void QgsRGBPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const


const QgsVector3D scale = pc->scale(); const QgsVector3D scale = pc->scale();
const QgsVector3D offset = pc->offset(); const QgsVector3D offset = pc->offset();
const double zValueOffset = context.zValueFixedOffset();


QgsContrastEnhancement *redContrastEnhancement = symbol->redContrastEnhancement(); QgsContrastEnhancement *redContrastEnhancement = symbol->redContrastEnhancement();
QgsContrastEnhancement *greenContrastEnhancement = symbol->greenContrastEnhancement(); QgsContrastEnhancement *greenContrastEnhancement = symbol->greenContrastEnhancement();
Expand All @@ -470,7 +473,7 @@ void QgsRGBPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const
qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 ); qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
double x = offset.x() + scale.x() * ix; double x = offset.x() + scale.x() * ix;
double y = offset.y() + scale.y() * iy; double y = offset.y() + scale.y() * iy;
double z = offset.z() + scale.z() * iz; double z = offset.z() + scale.z() * iz + zValueOffset;
QgsVector3D point( x, y, z ); QgsVector3D point( x, y, z );
QgsVector3D p = context.map().mapToWorldCoordinates( point ); QgsVector3D p = context.map().mapToWorldCoordinates( point );


Expand Down Expand Up @@ -595,6 +598,8 @@ void QgsClassificationPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex


const QgsVector3D scale = pc->scale(); const QgsVector3D scale = pc->scale();
const QgsVector3D offset = pc->offset(); const QgsVector3D offset = pc->offset();
const double zValueOffset = context.zValueFixedOffset();

QSet<int> filteredOutValues = context.getFilteredOutValues(); QSet<int> filteredOutValues = context.getFilteredOutValues();
for ( int i = 0; i < count; ++i ) for ( int i = 0; i < count; ++i )
{ {
Expand All @@ -604,7 +609,7 @@ void QgsClassificationPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex


double x = offset.x() + scale.x() * ix; double x = offset.x() + scale.x() * ix;
double y = offset.y() + scale.y() * iy; double y = offset.y() + scale.y() * iy;
double z = offset.z() + scale.z() * iz; double z = offset.z() + scale.z() * iz + zValueOffset;
QgsVector3D point( x, y, z ); QgsVector3D point( x, y, z );


QgsVector3D p = context.map().mapToWorldCoordinates( point ); QgsVector3D p = context.map().mapToWorldCoordinates( point );
Expand Down
9 changes: 9 additions & 0 deletions src/app/pointcloud/qgspointcloudlayerproperties.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "qgsmaplayerconfigwidget.h" #include "qgsmaplayerconfigwidget.h"
#include "qgspointcloudattributemodel.h" #include "qgspointcloudattributemodel.h"
#include "qgsdatumtransformdialog.h" #include "qgsdatumtransformdialog.h"
#include "qgspointcloudlayerelevationproperties.h"
#include <QFileDialog> #include <QFileDialog>
#include <QMenu> #include <QMenu>
#include <QMessageBox> #include <QMessageBox>
Expand Down Expand Up @@ -66,6 +67,8 @@ QgsPointCloudLayerProperties::QgsPointCloudLayerProperties( QgsPointCloudLayer *
metadataFrame->setLayout( layout ); metadataFrame->setLayout( layout );
mOptsPage_Metadata->setContentsMargins( 0, 0, 0, 0 ); mOptsPage_Metadata->setContentsMargins( 0, 0, 0, 0 );


mOffsetZSpinBox->setClearValue( 0 );

// update based on lyr's current state // update based on lyr's current state
syncToLayer(); syncToLayer();


Expand Down Expand Up @@ -146,6 +149,9 @@ void QgsPointCloudLayerProperties::apply()


mLayer->setName( mLayerOrigNameLineEdit->text() ); mLayer->setName( mLayerOrigNameLineEdit->text() );


// elevation tab
static_cast< QgsPointCloudLayerElevationProperties * >( mLayer->elevationProperties() )->setZOffset( mOffsetZSpinBox->value() );

for ( QgsMapLayerConfigWidget *w : mConfigWidgets ) for ( QgsMapLayerConfigWidget *w : mConfigWidgets )
w->apply(); w->apply();


Expand Down Expand Up @@ -185,6 +191,9 @@ void QgsPointCloudLayerProperties::syncToLayer()


mCrsSelector->setCrs( mLayer->crs() ); mCrsSelector->setCrs( mLayer->crs() );


// elevation tab
mOffsetZSpinBox->setValue( static_cast< const QgsPointCloudLayerElevationProperties * >( mLayer->elevationProperties() )->zOffset() );

for ( QgsMapLayerConfigWidget *w : mConfigWidgets ) for ( QgsMapLayerConfigWidget *w : mConfigWidgets )
w->syncToLayer( mLayer ); w->syncToLayer( mLayer );
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ void QgsPointCloudAttributeByRampRenderer::renderBlock( const QgsPointCloudBlock
if ( applyYOffset ) if ( applyYOffset )
attributeValue = context.offset().y() + context.scale().y() * attributeValue; attributeValue = context.offset().y() + context.scale().y() * attributeValue;
if ( applyZOffset ) if ( applyZOffset )
attributeValue = context.offset().z() + context.scale().z() * attributeValue; attributeValue = context.offset().z() + context.scale().z() * attributeValue + context.zValueFixedOffset();


mColorRampShader.shade( attributeValue, &red, &green, &blue, &alpha ); mColorRampShader.shade( attributeValue, &red, &green, &blue, &alpha );
drawPoint( x, y, QColor( red, green, blue, alpha ), context ); drawPoint( x, y, QColor( red, green, blue, alpha ), context );
Expand Down
10 changes: 7 additions & 3 deletions src/core/pointcloud/qgspointcloudlayerelevationproperties.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -28,14 +28,18 @@ bool QgsPointCloudLayerElevationProperties::hasElevation() const
return true; return true;
} }


QDomElement QgsPointCloudLayerElevationProperties::writeXml( QDomElement &, QDomDocument &document, const QgsReadWriteContext & ) QDomElement QgsPointCloudLayerElevationProperties::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext & )
{ {
QDomElement element = document.createElement( QStringLiteral( "elevation" ) ); QDomElement element = document.createElement( QStringLiteral( "elevation" ) );
element.setAttribute( QStringLiteral( "zoffset" ), qgsDoubleToString( mZOffset ) );
parentElement.appendChild( element );
return element; return element;
} }


bool QgsPointCloudLayerElevationProperties::readXml( const QDomElement &, const QgsReadWriteContext & ) bool QgsPointCloudLayerElevationProperties::readXml( const QDomElement &element, const QgsReadWriteContext & )
{ {
QDomElement elevationElement = element.firstChildElement( QStringLiteral( "elevation" ) ).toElement();
mZOffset = elevationElement.attribute( QStringLiteral( "zoffset" ), QStringLiteral( "0" ) ).toDouble();
return true; return true;
} }


Expand All @@ -56,7 +60,7 @@ QgsDoubleRange QgsPointCloudLayerElevationProperties::calculateZRange( QgsMapLay
const QVariant zMax = pcLayer->dataProvider()->metadataStatistic( QStringLiteral( "Z" ), QgsStatisticalSummary::Max ); const QVariant zMax = pcLayer->dataProvider()->metadataStatistic( QStringLiteral( "Z" ), QgsStatisticalSummary::Max );
if ( zMin.isValid() && zMax.isValid() ) if ( zMin.isValid() && zMax.isValid() )
{ {
return QgsDoubleRange( zMin.toDouble(), zMax.toDouble() ); return QgsDoubleRange( zMin.toDouble() + mZOffset, zMax.toDouble() + mZOffset );
} }
} }
} }
Expand Down
Loading

0 comments on commit 1963ef9

Please sign in to comment.