24#include <QJsonDocument>
45#include "qgspointcloudexpression.h"
49QgsRemoteCopcPointCloudIndex::QgsRemoteCopcPointCloudIndex() =
default;
51QgsRemoteCopcPointCloudIndex::~QgsRemoteCopcPointCloudIndex() =
default;
53std::unique_ptr<QgsPointCloudIndex> QgsRemoteCopcPointCloudIndex::clone()
const
55 QgsRemoteCopcPointCloudIndex *clone =
new QgsRemoteCopcPointCloudIndex;
56 QMutexLocker locker( &mHierarchyMutex );
57 copyCommonProperties( clone );
58 return std::unique_ptr<QgsPointCloudIndex>( clone );
61QList<IndexedPointCloudNode> QgsRemoteCopcPointCloudIndex::nodeChildren(
const IndexedPointCloudNode &n )
const
63 fetchNodeHierarchy( n );
65 mHierarchyMutex.lock();
66 Q_ASSERT( mHierarchy.contains( n ) );
67 QList<IndexedPointCloudNode> lst;
69 const int d = n.
d() + 1;
70 const int x = n.
x() * 2;
71 const int y = n.
y() * 2;
72 const int z = n.
z() * 2;
73 mHierarchyMutex.unlock();
75 for (
int i = 0; i < 8; ++i )
77 int dx = i & 1, dy = !!( i & 2 ), dz = !!( i & 4 );
79 if ( fetchNodeHierarchy( n2 ) && mHierarchy[n] >= 0 )
85void QgsRemoteCopcPointCloudIndex::load(
const QString &url )
89 mIsValid = mLazInfo->isValid();
92 mIsValid = loadSchema( *mLazInfo.get() );
100 mError = tr(
"Unable to recognize %1 as a LAZ file: \"%2\"" ).arg( url, mLazInfo->error() );
106 std::unique_ptr<QgsPointCloudBlockRequest> blockRequest( asyncNodeData( n, request ) );
114 if ( !blockRequest->block() )
116 QgsDebugMsg( QStringLiteral(
"Error downloading node %1 data, error : %2 " ).arg( n.
toString(), blockRequest->errorStr() ) );
119 return blockRequest->block();
124 if ( !fetchNodeHierarchy( n ) )
126 QMutexLocker locker( &mHierarchyMutex );
131 QgsPointCloudExpression filterExpression = mFilterExpression;
133 requestAttributes.
extend( attributes(), filterExpression.referencedAttributes() );
134 auto [ blockOffset, blockSize ] = mHierarchyNodePos.value( n );
135 int pointCount = mHierarchy.value( n );
138 scale(), offset(), filterExpression, request.
filterRect(),
139 blockOffset, blockSize, pointCount, *mLazInfo.get() );
144 return fetchNodeHierarchy( n );
149 QMutexLocker locker( &mHierarchyMutex );
151 QVector<IndexedPointCloudNode> ancestors;
153 while ( !mHierarchy.contains( foundRoot ) )
155 ancestors.push_front( foundRoot );
158 ancestors.push_front( foundRoot );
161 auto hierarchyIt = mHierarchy.constFind( n );
162 if ( hierarchyIt == mHierarchy.constEnd() )
165 int nodesCount = *hierarchyIt;
166 if ( nodesCount < 0 )
168 auto hierarchyNodePos = mHierarchyNodePos.constFind( n );
169 fetchHierarchyPage( hierarchyNodePos->first, hierarchyNodePos->second );
172 return mHierarchy.contains( n );
175bool QgsRemoteCopcPointCloudIndex::isValid()
const
180void QgsRemoteCopcPointCloudIndex::fetchHierarchyPage( uint64_t offset, uint64_t byteSize )
const
182 QNetworkRequest nr( mUrl );
183 nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
184 nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
185 QByteArray queryRange = QStringLiteral(
"bytes=%1-%2" ).arg( offset ).arg( offset + byteSize - 1 ).toLocal8Bit();
186 nr.setRawHeader(
"Range", queryRange );
194 if ( reply->error() != QNetworkReply::NoError )
196 QgsDebugMsg( QStringLiteral(
"Request failed: " ) + mUrl.toString() );
200 QByteArray data = reply->data();
218 for ( uint64_t i = 0; i < byteSize; i +=
sizeof( CopcEntry ) )
220 CopcEntry *entry =
reinterpret_cast<CopcEntry *
>( data.data() + i );
222 mHierarchy[nodeId] = entry->pointCount;
223 mHierarchyNodePos.insert( nodeId, QPair<uint64_t, int32_t>( entry->offset, entry->byteSize ) );
227void QgsRemoteCopcPointCloudIndex::copyCommonProperties( QgsRemoteCopcPointCloudIndex *destination )
const
229 QgsCopcPointCloudIndex::copyCommonProperties( destination );
232 destination->mUrl = mUrl;
233 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.
Base class for storing raw data from point cloud nodes.
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)