24 #include <QJsonDocument> 
   25 #include <QJsonObject> 
   48 QgsRemoteEptPointCloudIndex::QgsRemoteEptPointCloudIndex() : QgsEptPointCloudIndex()
 
   53 QgsRemoteEptPointCloudIndex::~QgsRemoteEptPointCloudIndex() = 
default;
 
   55 QList<IndexedPointCloudNode> QgsRemoteEptPointCloudIndex::nodeChildren( 
const IndexedPointCloudNode &n )
 const 
   57   QList<IndexedPointCloudNode> lst;
 
   58   if ( !loadNodeHierarchy( n ) )
 
   61   const int d = n.
d() + 1;
 
   62   const int x = n.
x() * 2;
 
   63   const int y = n.
y() * 2;
 
   64   const int z = n.
z() * 2;
 
   66   for ( 
int i = 0; i < 8; ++i )
 
   68     int dx = i & 1, dy = !!( i & 2 ), dz = !!( i & 4 );
 
   70     if ( loadNodeHierarchy( n2 ) )
 
   76 void QgsRemoteEptPointCloudIndex::load( 
const QString &url )
 
   80   QStringList splitUrl = url.split( 
'/' );
 
   82   mUrlFileNamePart = splitUrl.back();
 
   84   mUrlDirectoryPart = splitUrl.join( 
'/' );
 
   86   QNetworkRequest nr( url );
 
   92     QgsDebugMsg( QStringLiteral( 
"Request failed: " ) + url );
 
   98   mIsValid = loadSchema( reply.
content() );
 
  103   std::unique_ptr<QgsPointCloudBlockRequest> blockRequest( asyncNodeData( n, request ) );
 
  111   if ( !blockRequest->block() )
 
  113     QgsDebugMsg( QStringLiteral( 
"Error downloading node %1 data, error : %2 " ).arg( n.
toString(), blockRequest->errorStr() ) );
 
  116   return blockRequest->block();
 
  121   if ( !loadNodeHierarchy( n ) )
 
  125   if ( mDataType == QLatin1String( 
"binary" ) )
 
  127     fileUrl = QStringLiteral( 
"%1/ept-data/%2.bin" ).arg( mUrlDirectoryPart, n.
toString() );
 
  129   else if ( mDataType == QLatin1String( 
"zstandard" ) )
 
  131     fileUrl = QStringLiteral( 
"%1/ept-data/%2.zst" ).arg( mUrlDirectoryPart, n.
toString() );
 
  133   else if ( mDataType == QLatin1String( 
"laszip" ) )
 
  135     fileUrl = QStringLiteral( 
"%1/ept-data/%2.laz" ).arg( mUrlDirectoryPart, n.
toString() );
 
  147   return loadNodeHierarchy( n );
 
  152   mHierarchyMutex.lock();
 
  153   bool found = mHierarchy.contains( nodeId );
 
  154   mHierarchyMutex.unlock();
 
  158   QVector<IndexedPointCloudNode> nodePathToRoot;
 
  163       nodePathToRoot.push_back( currentNode );
 
  166     while ( currentNode.
d() >= 0 );
 
  169   for ( 
int i = nodePathToRoot.size() - 1; i >= 0 && !mHierarchy.contains( nodeId ); --i )
 
  173     mHierarchyMutex.lock();
 
  174     const bool foundInHierarchy = mHierarchy.contains( node );
 
  175     const bool foundInHierarchyNodes = mHierarchyNodes.contains( node );
 
  176     mHierarchyMutex.unlock();
 
  177     if ( foundInHierarchy )
 
  180     if ( !foundInHierarchyNodes )
 
  183     const QString fileUrl = QStringLiteral( 
"%1/ept-hierarchy/%2.json" ).arg( mUrlDirectoryPart, node.
toString() );
 
  184     QNetworkRequest nr( fileUrl );
 
  186     nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
 
  187     nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute, 
true );
 
  193       QgsDebugMsgLevel( QStringLiteral( 
"unable to read hierarchy from file %1" ).arg( fileUrl ), 2 );
 
  199     const QByteArray dataJsonH = reply.
content();
 
  200     QJsonParseError errH;
 
  201     const QJsonDocument docH = QJsonDocument::fromJson( dataJsonH, &errH );
 
  202     if ( errH.error != QJsonParseError::NoError )
 
  204       QgsDebugMsgLevel( QStringLiteral( 
"QJsonParseError when reading hierarchy from file %1" ).arg( fileUrl ), 2 );
 
  208     const QJsonObject rootHObj = docH.object();
 
  209     for ( 
auto it = rootHObj.constBegin(); it != rootHObj.constEnd(); ++it )
 
  211       const QString nodeIdStr = it.key();
 
  212       const int nodePointCount = it.value().toInt();
 
  214       mHierarchyMutex.lock();
 
  215       if ( nodePointCount > 0 )
 
  216         mHierarchy[nodeId] = nodePointCount;
 
  217       else if ( nodePointCount == -1 )
 
  218         mHierarchyNodes.insert( nodeId );
 
  219       mHierarchyMutex.unlock();
 
  223   mHierarchyMutex.lock();
 
  224   found = mHierarchy.contains( nodeId );
 
  225   mHierarchyMutex.unlock();
 
  230 bool QgsRemoteEptPointCloudIndex::isValid()
 const 
Represents a indexed point cloud node in octree.
static IndexedPointCloudNode fromString(const QString &str)
Creates node from string.
QString toString() const
Encode node to string.
IndexedPointCloudNode parentNode() const
Returns the parent of the node.
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
ErrorCode get(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr)
Performs a "get" operation on the specified request.
@ NoError
No error was encountered.
QgsNetworkReplyContent reply() const
Returns the content of the network reply, after a get() or post() request has been made.
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
QByteArray content() const
Returns the reply content.
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.
#define QgsDebugMsgLevel(str, level)