24 #include <QJsonDocument> 
   25 #include <QJsonObject> 
   45 #include "qgspointcloudexpression.h" 
   49 QgsRemoteCopcPointCloudIndex::QgsRemoteCopcPointCloudIndex() = 
default;
 
   51 QgsRemoteCopcPointCloudIndex::~QgsRemoteCopcPointCloudIndex() = 
default;
 
   53 std::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 );
 
   61 QList<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 )
 
   85 void 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,
 
  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 );
 
  175 bool QgsRemoteCopcPointCloudIndex::isValid()
 const 
  180 void 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 ) );
 
  227 void QgsRemoteCopcPointCloudIndex::copyCommonProperties( QgsRemoteCopcPointCloudIndex *destination )
 const 
  229   QgsCopcPointCloudIndex::copyCommonProperties( destination );
 
  232   destination->mUrl = mUrl;
 
  233   destination->mHierarchyNodes = mHierarchyNodes;