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 if ( !blockRequest->block() )
109 QgsDebugError( QStringLiteral(
"Error downloading node %1 data, error : %2 " ).arg( n.
toString(), blockRequest->errorStr() ) );
112 return blockRequest->block();
117 if ( !fetchNodeHierarchy( n ) )
119 QMutexLocker locker( &mHierarchyMutex );
124 QgsPointCloudExpression filterExpression = mFilterExpression;
126 requestAttributes.
extend( attributes(), filterExpression.referencedAttributes() );
127 auto [ blockOffset, blockSize ] = mHierarchyNodePos.value( n );
128 int pointCount = mHierarchy.value( n );
131 scale(), offset(), filterExpression, request.
filterRect(),
132 blockOffset, blockSize, pointCount, *mLazInfo.get() );
137 return fetchNodeHierarchy( n );
142 QMutexLocker locker( &mHierarchyMutex );
144 QVector<IndexedPointCloudNode> ancestors;
146 while ( !mHierarchy.contains( foundRoot ) )
148 ancestors.push_front( foundRoot );
151 ancestors.push_front( foundRoot );
154 auto hierarchyIt = mHierarchy.constFind( n );
155 if ( hierarchyIt == mHierarchy.constEnd() )
158 int nodesCount = *hierarchyIt;
159 if ( nodesCount < 0 )
161 auto hierarchyNodePos = mHierarchyNodePos.constFind( n );
162 fetchHierarchyPage( hierarchyNodePos->first, hierarchyNodePos->second );
165 return mHierarchy.contains( n );
168bool QgsRemoteCopcPointCloudIndex::isValid()
const
173void QgsRemoteCopcPointCloudIndex::fetchHierarchyPage( uint64_t offset, uint64_t byteSize )
const
175 QNetworkRequest nr( mUrl );
177 nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
178 nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
179 QByteArray queryRange = QStringLiteral(
"bytes=%1-%2" ).arg( offset ).arg( offset + byteSize - 1 ).toLocal8Bit();
180 nr.setRawHeader(
"Range", queryRange );
188 if ( reply->error() != QNetworkReply::NoError )
190 QgsDebugError( QStringLiteral(
"Request failed: " ) + mUrl.toString() );
194 QByteArray data = reply->data();
212 for ( uint64_t i = 0; i < byteSize; i +=
sizeof( CopcEntry ) )
214 CopcEntry *entry =
reinterpret_cast<CopcEntry *
>( data.data() + i );
216 mHierarchy[nodeId] = entry->pointCount;
217 mHierarchyNodePos.insert( nodeId, QPair<uint64_t, int32_t>( entry->offset, entry->byteSize ) );
221void QgsRemoteCopcPointCloudIndex::copyCommonProperties( QgsRemoteCopcPointCloudIndex *destination )
const
223 QgsCopcPointCloudIndex::copyCommonProperties( destination );
226 destination->mUrl = mUrl;
227 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)
#define QgsDebugError(str)
#define QgsSetRequestInitiatorClass(request, _class)