Skip to content
Permalink
Browse files

[pointclouds] QgsPointCloudBlock (#39651)

* introduce qgspointcloudblock

* expand attributes based on request

* add point cloud request

* fix header

* fix rendering

* fix build

* fix build

* fix builds

* intent

* fixes after Martin's review
  • Loading branch information
PeterPetrik committed Oct 30, 2020
1 parent d0ea8fa commit ce466a4726519b49bcb04d1bf82f895a3879a95f
@@ -28,6 +28,8 @@

#include "qgsapplication.h"
#include "qgs3dsymbolregistry.h"
#include "qgspointcloudattribute.h"
#include "qgspointcloudrequest.h"

#include <QtConcurrent>
#include <Qt3DRender/QAttribute>
@@ -104,27 +106,39 @@ bool QgsPointCloud3DSymbolHandler::prepare( const Qgs3DRenderContext &context )

void QgsPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const Qgs3DRenderContext &context )
{
const QVector<qint32> data = pc->nodePositionDataAsInt32( n );
const QVector<char> classes = pc->nodeClassesDataAsChar( n );
QgsPointCloudAttributeCollection attributes;
attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "X" ), QgsPointCloudAttribute::Int32 ) );
attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Y" ), QgsPointCloudAttribute::Int32 ) );
attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Z" ), QgsPointCloudAttribute::Int32 ) );
attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Classification" ), QgsPointCloudAttribute::Char ) );
QgsPointCloudRequest request;
request.setAttributes( attributes );
std::unique_ptr<QgsPointCloudBlock> block( pc->nodeData( n, request ) );
if ( !block )
return;

const char *ptr = block->data();
int count = block->pointCount();
int recordSize = attributes.pointRecordSize();

const QgsVector3D scale = pc->scale();
const QgsVector3D offset = pc->offset();

const qint32 *ptr = data.constData();
int count = data.count() / 3;
for ( int i = 0; i < count; ++i )
{
qint32 ix = ptr[i * 3 + 0];
qint32 iy = ptr[i * 3 + 1];
qint32 iz = ptr[i * 3 + 2];
qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
char cls = *( char * )( ptr + i * recordSize + 12 );

double x = offset.x() + scale.x() * ix;
double y = offset.y() + scale.y() * iy;
double z = offset.z() + scale.z() * iz;
QVector3D point( x, y, z );
QgsVector3D p = context.map().mapToWorldCoordinates( point );
outNormal.positions.push_back( QVector3D( p.x(), p.y(), p.z() ) );
outNormal.classes.push_back( cls );
}
outNormal.classes.append( classes );
}

void QgsPointCloud3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
@@ -630,6 +630,9 @@ SET(QGIS_CORE_SRCS
mesh/qgsmeshcalcutils.cpp
mesh/qgsmeshvirtualdatasetgroup.cpp

pointcloud/qgspointcloudattribute.cpp
pointcloud/qgspointcloudrequest.cpp
pointcloud/qgspointcloudblock.cpp
pointcloud/qgspointcloudlayer.cpp
pointcloud/qgspointcloudrenderer.cpp
pointcloud/qgspointcloudindex.cpp
@@ -1308,6 +1311,9 @@ SET(QGIS_CORE_HDRS
mesh/qgsmeshcalcutils.h
mesh/qgsmeshvirtualdatasetgroup.h

pointcloud/qgspointcloudattribute.h
pointcloud/qgspointcloudrequest.h
pointcloud/qgspointcloudblock.h
pointcloud/qgspointcloudlayer.h
pointcloud/qgspointcloudrenderer.h
pointcloud/qgspointcloudindex.h
@@ -0,0 +1,114 @@
/***************************************************************************
qgspointcloudattribute.cpp
-----------------------
begin : October 2020
copyright : (C) 2020 by Peter Petrik
email : zilolv 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 "qgis.h"
#include "qgspointcloudattribute.h"

QgsPointCloudAttribute::QgsPointCloudAttribute() = default;

QgsPointCloudAttribute::QgsPointCloudAttribute( const QString &name, DataType type )
: mName( name )
, mType( type )
{
updateSize();
}

QString QgsPointCloudAttribute::name() const
{
return mName;
}

size_t QgsPointCloudAttribute::size() const
{
return mSize;
}

QgsPointCloudAttribute::DataType QgsPointCloudAttribute::type() const
{
return mType;
}

void QgsPointCloudAttribute::updateSize()
{
switch ( mType )
{
case DataType::Char:
mSize = 1;
break;
case DataType::Short:
mSize = 2;
break;
case DataType::Float:
mSize = 4;
break;
case DataType::Int32:
mSize = 4;
break;
case DataType::Double:
mSize = 8;
break;
}
}

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

QgsPointCloudAttributeCollection::QgsPointCloudAttributeCollection() = default;

QgsPointCloudAttributeCollection::QgsPointCloudAttributeCollection( const QVector<QgsPointCloudAttribute> &attributes )
: mAttributes( attributes )
{
for ( int i = 0; i < mAttributes.size(); ++i )
{
const QgsPointCloudAttribute &attribute = mAttributes.at( i );
mSize += attribute.size();
}

}

void QgsPointCloudAttributeCollection::push_back( const QgsPointCloudAttribute &attribute )
{
mAttributes.push_back( attribute );
mSize += attribute.size();
}

QVector<QgsPointCloudAttribute> QgsPointCloudAttributeCollection::attributes() const
{
return mAttributes;
}

const QgsPointCloudAttribute *QgsPointCloudAttributeCollection::find( const QString &attributeName, int &offset ) const
{

int off = 0;

for ( int i = 0; i < mAttributes.size(); ++i )
{
const QgsPointCloudAttribute &attr = mAttributes.at( i );
if ( attr.name() == attributeName )
{
offset = off;
return &attr;
}
else
{
off += attr.size();
}
}

// not found
return nullptr;
}
@@ -0,0 +1,106 @@
/***************************************************************************
qgspointcloudattribute.h
---------------------
begin : October 2020
copyright : (C) 2020 by Peter Petrik
email : zilolv 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 QGSPOINTCLOUDATTRIBUTE_H
#define QGSPOINTCLOUDATTRIBUTE_H

#include "qgis.h"
#include "qgis_core.h"
#include <QString>
#include <QVector>

#define SIP_NO_FILE

/**
* \ingroup core
*
* Attribute for point cloud data
* pair of name and size in bytes
*
* \since QGIS 3.18
*/
class CORE_EXPORT QgsPointCloudAttribute
{
public:
//! Systems of unit measurement
enum DataType
{
Char, //!< Char 1 byte
Short, //!< Short int 2 bytes
Int32, //!< Int32 4 bytes
Float, //!< Float 4 bytes
Double, //!< Double 8 bytes
};

//! Ctor
QgsPointCloudAttribute();
//! Ctor
QgsPointCloudAttribute( const QString &name, DataType type );

//! Returns name of the attribute
QString name() const;

//! Returns size of the attribute in bytes
size_t size() const;

//! Returns the data type
DataType type() const;

private:
void updateSize();

QString mName;
size_t mSize = 0;
DataType mType;
};

/**
* \ingroup core
*
* Collection of point cloud attributes
*
* \since QGIS 3.18
*/
class CORE_EXPORT QgsPointCloudAttributeCollection
{
public:
//! Ctor
QgsPointCloudAttributeCollection();
//! Ctor with given attributes
QgsPointCloudAttributeCollection( const QVector<QgsPointCloudAttribute> &attributes );
//! Adds extra attribute
void push_back( const QgsPointCloudAttribute &attribute );

//! Returns all attributes
QVector<QgsPointCloudAttribute> attributes() const;

/**
* Finds the attribute with the name
*
* Returns nullptr if not found
*/
const QgsPointCloudAttribute *find( const QString &attributeName, int &offset ) const;

//! Returns total size of record
int pointRecordSize() const { return mSize; }

private:
int mSize = 0;
QVector<QgsPointCloudAttribute> mAttributes;
};

#endif // QGSPOINTCLOUDATTRIBUTE_H
@@ -0,0 +1,49 @@
/***************************************************************************
qgspointcloudblock.cpp
-----------------------
begin : October 2020
copyright : (C) 2020 by Peter Petrik
email : zilolv 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 "qgis.h"
#include "qgspointcloudblock.h"
#include "qgspointcloudattribute.h"


QgsPointCloudBlock::QgsPointCloudBlock(
int count,
const QgsPointCloudAttributeCollection &attributes,
const QByteArray &data
)
: mPointCount( count )
, mAttributes( attributes )
, mStorage( data )
{
}

QgsPointCloudBlock::~QgsPointCloudBlock() = default;

const char *QgsPointCloudBlock::data() const
{
return mStorage.data();
}

int QgsPointCloudBlock::pointCount() const
{
return mPointCount;
}

QgsPointCloudAttributeCollection QgsPointCloudBlock::attributes() const
{
return mAttributes;
}

1 comment on commit ce466a4

@rduivenvoorde

This comment has been minimized.

Copy link
Contributor

@rduivenvoorde rduivenvoorde commented on ce466a4 Oct 30, 2020

Don't want to be seen as impatient :-)
So eager to see a pointcloud (on linux without wine-stuff there is no lastools....)
But... what kind of files should I be able to open with this? I had a netcdf and a las file around...
Maybe there is some small (testable) dataset to share?
Don't take this as push... no stress! Just very curious ;-)

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