Skip to content

Commit

Permalink
Fix point cloud 2d identify when x/y/z values in dataset are not inte…
Browse files Browse the repository at this point in the history
…ger values
  • Loading branch information
nyalldawson authored and wonder-sk committed Jan 5, 2021
1 parent cc0f4c3 commit 1808a44
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 19 deletions.
4 changes: 2 additions & 2 deletions src/core/pointcloud/qgseptdecoder.cpp
Expand Up @@ -385,7 +385,7 @@ QgsPointCloudBlock *QgsEptDecoder::decompressLaz( const QString &filename,
else else
{ {
// this can possibly happen -- e.g. if a style built using a different point cloud format references an attribute which isn't available from the laz file // this can possibly happen -- e.g. if a style built using a different point cloud format references an attribute which isn't available from the laz file
requestedAttributeDetails.emplace_back( RequestedAttributeDetails( LazAttribute::MissingOrUnknown, QgsPointCloudAttribute::Char, 1 ) ); requestedAttributeDetails.emplace_back( RequestedAttributeDetails( LazAttribute::MissingOrUnknown, requestedAttribute.type(), requestedAttribute.size() ) );
} }
} }


Expand Down Expand Up @@ -446,7 +446,7 @@ QgsPointCloudBlock *QgsEptDecoder::decompressLaz( const QString &filename,
break; break;
case LazAttribute::MissingOrUnknown: case LazAttribute::MissingOrUnknown:
// just store 0 for unknown/missing attributes // just store 0 for unknown/missing attributes
dataBuffer[ outputOffset ] = 0; _storeToStream<unsigned short>( dataBuffer, outputOffset, requestedAttribute.type, 0 );
break; break;
} }


Expand Down
64 changes: 47 additions & 17 deletions src/core/pointcloud/qgspointclouddataprovider.cpp
Expand Up @@ -181,24 +181,55 @@ QVariant QgsPointCloudDataProvider::metadataClassStatistic( const QString &, con
return QVariant(); return QVariant();
} }


/** template <typename T>
* Retrieves the x & y values for the point at index \a i. void _attribute( const char *data, std::size_t offset, QgsPointCloudAttribute::DataType type, T &value )
*/
static void _pointXY( const char *ptr, int i, std::size_t pointRecordSize, int xOffset, int yOffset, const QgsVector3D &indexScale, const QgsVector3D &indexOffset, double &x, double &y )
{ {
const qint32 ix = *reinterpret_cast< const qint32 * >( ptr + i * pointRecordSize + xOffset ); switch ( type )
const qint32 iy = *reinterpret_cast< const qint32 * >( ptr + i * pointRecordSize + yOffset ); {
x = indexOffset.x() + indexScale.x() * ix; case QgsPointCloudAttribute::Char:
y = indexOffset.y() + indexScale.y() * iy; value = *( data + offset );
break;

case QgsPointCloudAttribute::Int32:
value = *reinterpret_cast< const qint32 * >( data + offset );
break;

case QgsPointCloudAttribute::Short:
{
value = *reinterpret_cast< const short * >( data + offset );
}
break;

case QgsPointCloudAttribute::UShort:
value = *reinterpret_cast< const unsigned short * >( data + offset );
break;

case QgsPointCloudAttribute::Float:
value = static_cast< T >( *reinterpret_cast< const float * >( data + offset ) );
break;

case QgsPointCloudAttribute::Double:
value = *reinterpret_cast< const double * >( data + offset );
break;
}
} }


/** /**
* Retrieves the z value for the point at index \a i. * Retrieves the x, y, z values for the point at index \a i.
*/ */
static double _pointZ( const char *ptr, int i, std::size_t pointRecordSize, int zOffset, const QgsVector3D &indexScale, const QgsVector3D &indexOffset ) static void _pointXYZ( const char *ptr, int i, std::size_t pointRecordSize, int xOffset, QgsPointCloudAttribute::DataType xType,
int yOffset, QgsPointCloudAttribute::DataType yType,
int zOffset, QgsPointCloudAttribute::DataType zType,
const QgsVector3D &indexScale, const QgsVector3D &indexOffset, double &x, double &y, double &z )
{ {
const qint32 iz = *reinterpret_cast<const qint32 * >( ptr + i * pointRecordSize + zOffset ); _attribute( ptr, i * pointRecordSize + xOffset, xType, x );
return indexOffset.z() + indexScale.z() * iz; x = indexOffset.x() + indexScale.x() * x;

_attribute( ptr, i * pointRecordSize + yOffset, yType, y );
y = indexOffset.y() + indexScale.y() * y;

_attribute( ptr, i * pointRecordSize + zOffset, zType, z );
z = indexOffset.z() + indexScale.z() * z;
} }


/** /**
Expand Down Expand Up @@ -282,16 +313,15 @@ struct MapIndexedPointCloudNode
QgsPointCloudAttributeCollection blockAttributes = block->attributes(); QgsPointCloudAttributeCollection blockAttributes = block->attributes();
const std::size_t recordSize = blockAttributes.pointRecordSize(); const std::size_t recordSize = blockAttributes.pointRecordSize();
int xOffset, yOffset, zOffset; int xOffset, yOffset, zOffset;
blockAttributes.find( QStringLiteral( "X" ), xOffset ); const QgsPointCloudAttribute::DataType xType = blockAttributes.find( QStringLiteral( "X" ), xOffset )->type();
blockAttributes.find( QStringLiteral( "Y" ), yOffset ); const QgsPointCloudAttribute::DataType yType = blockAttributes.find( QStringLiteral( "Y" ), yOffset )->type();
blockAttributes.find( QStringLiteral( "Z" ), zOffset ); const QgsPointCloudAttribute::DataType zType = blockAttributes.find( QStringLiteral( "Z" ), zOffset )->type();
std::unique_ptr< QgsGeometryEngine > extentEngine( QgsGeometry::createGeometryEngine( mExtentGeometry.constGet() ) ); std::unique_ptr< QgsGeometryEngine > extentEngine( QgsGeometry::createGeometryEngine( mExtentGeometry.constGet() ) );
extentEngine->prepareGeometry(); extentEngine->prepareGeometry();
for ( int i = 0; i < block->pointCount() && pointsCount < mPointsLimit; ++i ) for ( int i = 0; i < block->pointCount() && pointsCount < mPointsLimit; ++i )
{ {
double x, y, z; double x, y, z;
_pointXY( ptr, i, recordSize, xOffset, yOffset, mIndexScale, mIndexOffset, x, y ); _pointXYZ( ptr, i, recordSize, xOffset, xType, yOffset, yType, zOffset, zType, mIndexScale, mIndexOffset, x, y, z );
z = _pointZ( ptr, i, recordSize, zOffset, mIndexScale, mIndexOffset );
QgsPoint pointXY( x, y ); QgsPoint pointXY( x, y );


if ( mZRange.contains( z ) && extentEngine->contains( &pointXY ) ) if ( mZRange.contains( z ) && extentEngine->contains( &pointXY ) )
Expand Down
4 changes: 4 additions & 0 deletions src/core/pointcloud/qgspointcloudrenderer.h
Expand Up @@ -487,6 +487,8 @@ class CORE_EXPORT QgsPointCloudRenderer
*/ */
static void pointXY( QgsPointCloudRenderContext &context, const char *ptr, int i, double &x, double &y ) static void pointXY( QgsPointCloudRenderContext &context, const char *ptr, int i, double &x, double &y )
{ {
// be wary when copying this code!! In the renderer we explicitly request x/y/z as qint32 values, but in other
// situations these may be floats or doubles!
const qint32 ix = *reinterpret_cast< const qint32 * >( ptr + i * context.pointRecordSize() + context.xOffset() ); const qint32 ix = *reinterpret_cast< const qint32 * >( ptr + i * context.pointRecordSize() + context.xOffset() );
const qint32 iy = *reinterpret_cast< const qint32 * >( ptr + i * context.pointRecordSize() + context.yOffset() ); const qint32 iy = *reinterpret_cast< const qint32 * >( ptr + i * context.pointRecordSize() + context.yOffset() );
x = context.offset().x() + context.scale().x() * ix; x = context.offset().x() + context.scale().x() * ix;
Expand All @@ -498,6 +500,8 @@ class CORE_EXPORT QgsPointCloudRenderer
*/ */
static double pointZ( QgsPointCloudRenderContext &context, const char *ptr, int i ) static double pointZ( QgsPointCloudRenderContext &context, const char *ptr, int i )
{ {
// be wary when copying this code!! In the renderer we explicitly request x/y/z as qint32 values, but in other
// situations these may be floats or doubles!
const qint32 iz = *reinterpret_cast<const qint32 * >( ptr + i * context.pointRecordSize() + context.zOffset() ); const qint32 iz = *reinterpret_cast<const qint32 * >( ptr + i * context.pointRecordSize() + context.zOffset() );
return ( context.offset().z() + context.scale().z() * iz ) * context.zValueScale() + context.zValueFixedOffset(); return ( context.offset().z() + context.scale().z() * iz ) * context.zValueScale() + context.zValueFixedOffset();
} }
Expand Down

0 comments on commit 1808a44

Please sign in to comment.