24 #include <QJsonDocument> 
   25 #include <QJsonObject> 
   45 #include "qgspointcloudexpression.h" 
   49 QgsRemoteEptPointCloudIndex::QgsRemoteEptPointCloudIndex() : QgsEptPointCloudIndex()
 
   54 QgsRemoteEptPointCloudIndex::~QgsRemoteEptPointCloudIndex() = 
default;
 
   56 std::unique_ptr<QgsPointCloudIndex> QgsRemoteEptPointCloudIndex::clone()
 const 
   58   QgsRemoteEptPointCloudIndex *clone = 
new QgsRemoteEptPointCloudIndex;
 
   59   QMutexLocker locker( &mHierarchyMutex );
 
   60   copyCommonProperties( clone );
 
   61   return std::unique_ptr<QgsPointCloudIndex>( clone );
 
   64 QList<IndexedPointCloudNode> QgsRemoteEptPointCloudIndex::nodeChildren( 
const IndexedPointCloudNode &n )
 const 
   66   QList<IndexedPointCloudNode> lst;
 
   67   if ( !loadNodeHierarchy( n ) )
 
   70   const int d = n.
d() + 1;
 
   71   const int x = n.
x() * 2;
 
   72   const int y = n.
y() * 2;
 
   73   const int z = n.
z() * 2;
 
   76   for ( 
int i = 0; i < 8; ++i )
 
   78     int dx = i & 1, dy = !!( i & 2 ), dz = !!( i & 4 );
 
   80     if ( loadNodeHierarchy( n2 ) )
 
   86 void QgsRemoteEptPointCloudIndex::load( 
const QString &url )
 
   90   QStringList splitUrl = url.split( 
'/' );
 
   92   mUrlFileNamePart = splitUrl.back();
 
   94   mUrlDirectoryPart = splitUrl.join( 
'/' );
 
   96   QNetworkRequest nr( url );
 
  102     QgsDebugMsg( QStringLiteral( 
"Request failed: " ) + url );
 
  108   mIsValid = loadSchema( reply.
content() );
 
  113   std::unique_ptr<QgsPointCloudBlockRequest> blockRequest( asyncNodeData( n, request ) );
 
  121   if ( !blockRequest->block() )
 
  123     QgsDebugMsg( QStringLiteral( 
"Error downloading node %1 data, error : %2 " ).arg( n.
toString(), blockRequest->errorStr() ) );
 
  126   return blockRequest->block();
 
  131   if ( !loadNodeHierarchy( n ) )
 
  135   if ( mDataType == QLatin1String( 
"binary" ) )
 
  137     fileUrl = QStringLiteral( 
"%1/ept-data/%2.bin" ).arg( mUrlDirectoryPart, n.
toString() );
 
  139   else if ( mDataType == QLatin1String( 
"zstandard" ) )
 
  141     fileUrl = QStringLiteral( 
"%1/ept-data/%2.zst" ).arg( mUrlDirectoryPart, n.
toString() );
 
  143   else if ( mDataType == QLatin1String( 
"laszip" ) )
 
  145     fileUrl = QStringLiteral( 
"%1/ept-data/%2.laz" ).arg( mUrlDirectoryPart, n.
toString() );
 
  155   QgsPointCloudExpression filterExpression = mFilterExpression;
 
  157   requestAttributes.
extend( attributes(), filterExpression.referencedAttributes() );
 
  163   return loadNodeHierarchy( n );
 
  168   mHierarchyMutex.lock();
 
  169   bool found = mHierarchy.contains( nodeId );
 
  170   mHierarchyMutex.unlock();
 
  174   QVector<IndexedPointCloudNode> nodePathToRoot;
 
  179       nodePathToRoot.push_back( currentNode );
 
  182     while ( currentNode.
d() >= 0 );
 
  185   for ( 
int i = nodePathToRoot.size() - 1; i >= 0 && !mHierarchy.contains( nodeId ); --i )
 
  189     mHierarchyMutex.lock();
 
  190     const bool foundInHierarchy = mHierarchy.contains( node );
 
  191     const bool foundInHierarchyNodes = mHierarchyNodes.contains( node );
 
  192     mHierarchyMutex.unlock();
 
  193     if ( foundInHierarchy )
 
  196     if ( !foundInHierarchyNodes )
 
  199     const QString fileUrl = QStringLiteral( 
"%1/ept-hierarchy/%2.json" ).arg( mUrlDirectoryPart, node.
toString() );
 
  200     QNetworkRequest nr( fileUrl );
 
  202     nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
 
  203     nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute, 
true );
 
  209       QgsDebugMsgLevel( QStringLiteral( 
"unable to read hierarchy from file %1" ).arg( fileUrl ), 2 );
 
  215     const QByteArray dataJsonH = reply.
content();
 
  216     QJsonParseError errH;
 
  217     const QJsonDocument docH = QJsonDocument::fromJson( dataJsonH, &errH );
 
  218     if ( errH.error != QJsonParseError::NoError )
 
  220       QgsDebugMsgLevel( QStringLiteral( 
"QJsonParseError when reading hierarchy from file %1" ).arg( fileUrl ), 2 );
 
  224     const QJsonObject rootHObj = docH.object();
 
  225     for ( 
auto it = rootHObj.constBegin(); it != rootHObj.constEnd(); ++it )
 
  227       const QString nodeIdStr = it.key();
 
  228       const int nodePointCount = it.value().toInt();
 
  230       mHierarchyMutex.lock();
 
  231       if ( nodePointCount > 0 )
 
  232         mHierarchy[nodeId] = nodePointCount;
 
  233       else if ( nodePointCount == -1 )
 
  234         mHierarchyNodes.insert( nodeId );
 
  235       mHierarchyMutex.unlock();
 
  239   mHierarchyMutex.lock();
 
  240   found = mHierarchy.contains( nodeId );
 
  241   mHierarchyMutex.unlock();
 
  246 bool QgsRemoteEptPointCloudIndex::isValid()
 const 
  251 void QgsRemoteEptPointCloudIndex::copyCommonProperties( QgsRemoteEptPointCloudIndex *destination )
 const 
  253   QgsEptPointCloudIndex::copyCommonProperties( destination );
 
  256   destination->mUrlDirectoryPart = mUrlDirectoryPart;
 
  257   destination->mUrlFileNamePart = mUrlFileNamePart;
 
  258   destination->mUrl = mUrl;
 
  259   destination->mHierarchyNodes = mHierarchyNodes;