24#include <QJsonDocument>
37#include "qgspointcloudexpression.h"
42QgsRemoteCopcPointCloudIndex::QgsRemoteCopcPointCloudIndex() =
default;
44QgsRemoteCopcPointCloudIndex::~QgsRemoteCopcPointCloudIndex() =
default;
46std::unique_ptr<QgsPointCloudIndex> QgsRemoteCopcPointCloudIndex::clone()
const
48 QgsRemoteCopcPointCloudIndex *clone =
new QgsRemoteCopcPointCloudIndex;
49 QMutexLocker locker( &mHierarchyMutex );
50 copyCommonProperties( clone );
51 return std::unique_ptr<QgsPointCloudIndex>( clone );
54QList<IndexedPointCloudNode> QgsRemoteCopcPointCloudIndex::nodeChildren(
const IndexedPointCloudNode &n )
const
56 fetchNodeHierarchy( n );
58 mHierarchyMutex.lock();
59 Q_ASSERT( mHierarchy.contains( n ) );
60 QList<IndexedPointCloudNode> lst;
62 const int d = n.
d() + 1;
63 const int x = n.
x() * 2;
64 const int y = n.
y() * 2;
65 const int z = n.
z() * 2;
66 mHierarchyMutex.unlock();
68 for (
int i = 0; i < 8; ++i )
70 int dx = i & 1, dy = !!( i & 2 ), dz = !!( i & 4 );
72 if ( fetchNodeHierarchy( n2 ) && mHierarchy[n] >= 0 )
78void QgsRemoteCopcPointCloudIndex::load(
const QString &url )
82 mIsValid = mLazInfo->isValid();
85 mIsValid = loadSchema( *mLazInfo.get() );
93 mError = tr(
"Unable to recognize %1 as a LAZ file: \"%2\"" ).arg( url, mLazInfo->error() );
99 std::unique_ptr<QgsPointCloudBlockRequest> blockRequest( asyncNodeData( n, request ) );
107 std::unique_ptr<QgsPointCloudBlock> block = blockRequest->takeBlock();
111 QgsDebugError( QStringLiteral(
"Error downloading node %1 data, error : %2 " ).arg( n.
toString(), blockRequest->errorStr() ) );
119 if ( !fetchNodeHierarchy( n ) )
121 QMutexLocker locker( &mHierarchyMutex );
126 QgsPointCloudExpression filterExpression = mFilterExpression;
128 requestAttributes.
extend( attributes(), filterExpression.referencedAttributes() );
129 auto [ blockOffset, blockSize ] = mHierarchyNodePos.value( n );
130 int pointCount = mHierarchy.value( n );
133 scale(), offset(), filterExpression, request.
filterRect(),
134 blockOffset, blockSize, pointCount, *mLazInfo.get() );
139 return fetchNodeHierarchy( n );
144 QMutexLocker locker( &mHierarchyMutex );
146 QVector<IndexedPointCloudNode> ancestors;
148 while ( !mHierarchy.contains( foundRoot ) )
150 ancestors.push_front( foundRoot );
153 ancestors.push_front( foundRoot );
156 auto hierarchyIt = mHierarchy.constFind( n );
157 if ( hierarchyIt == mHierarchy.constEnd() )
160 int nodesCount = *hierarchyIt;
161 if ( nodesCount < 0 )
163 auto hierarchyNodePos = mHierarchyNodePos.constFind( n );
164 fetchHierarchyPage( hierarchyNodePos->first, hierarchyNodePos->second );
167 return mHierarchy.contains( n );
170bool QgsRemoteCopcPointCloudIndex::isValid()
const
175void QgsRemoteCopcPointCloudIndex::fetchHierarchyPage( uint64_t offset, uint64_t byteSize )
const
177 QNetworkRequest nr( mUrl );
179 nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
180 nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
181 QByteArray queryRange = QStringLiteral(
"bytes=%1-%2" ).arg( offset ).arg( offset + byteSize - 1 ).toLocal8Bit();
182 nr.setRawHeader(
"Range", queryRange );
190 if ( reply->error() != QNetworkReply::NoError )
192 QgsDebugError( QStringLiteral(
"Request failed: " ) + mUrl.toString() );
196 QByteArray data = reply->data();
214 for ( uint64_t i = 0; i < byteSize; i +=
sizeof( CopcEntry ) )
216 CopcEntry *entry =
reinterpret_cast<CopcEntry *
>( data.data() + i );
218 mHierarchy[nodeId] = entry->pointCount;
219 mHierarchyNodePos.insert( nodeId, QPair<uint64_t, int32_t>( entry->offset, entry->byteSize ) );
223void QgsRemoteCopcPointCloudIndex::copyCommonProperties( QgsRemoteCopcPointCloudIndex *destination )
const
225 QgsCopcPointCloudIndex::copyCommonProperties( destination );
228 destination->mUrl = mUrl;
229 destination->mHierarchyNodes = mHierarchyNodes;
Represents a indexed point cloud node in octree.
QString toString() const
Encode node to string.
IndexedPointCloudNode parentNode() const
Returns the parent of the node.
static QgsTileDownloadManager * tileDownloadManager()
Returns the application's tile download manager, used for download of map tiles when rendering.
Base class for handling loading QgsPointCloudBlock asynchronously from a remote COPC dataset.
Class for extracting information contained in LAZ file such as the public header block and variable l...
static QgsLazInfo fromUrl(QUrl &url)
Static function to create a QgsLazInfo class from a file over network.
Collection of point cloud attributes.
void extend(const QgsPointCloudAttributeCollection &otherCollection, const QSet< QString > &matchingNames)
Adds specific missing attributes from another QgsPointCloudAttributeCollection.
Base class for handling loading QgsPointCloudBlock asynchronously.
void finished()
Emitted when the request processing has finished.
Point cloud data request.
QgsPointCloudAttributeCollection attributes() const
Returns attributes.
QgsRectangle filterRect() const
Returns the rectangle from which points will be taken, in point cloud's crs.
void finished()
Emitted when the reply has finished (either with a success or with a failure)
#define QgsDebugError(str)
#define QgsSetRequestInitiatorClass(request, _class)