24#include <QJsonDocument>
39#include "qgspointcloudexpression.h"
44QgsRemoteEptPointCloudIndex::QgsRemoteEptPointCloudIndex() : QgsEptPointCloudIndex()
49QgsRemoteEptPointCloudIndex::~QgsRemoteEptPointCloudIndex() =
default;
51std::unique_ptr<QgsPointCloudIndex> QgsRemoteEptPointCloudIndex::clone()
const
53 QgsRemoteEptPointCloudIndex *clone =
new QgsRemoteEptPointCloudIndex;
54 QMutexLocker locker( &mHierarchyMutex );
55 copyCommonProperties( clone );
56 return std::unique_ptr<QgsPointCloudIndex>( clone );
59QList<IndexedPointCloudNode> QgsRemoteEptPointCloudIndex::nodeChildren(
const IndexedPointCloudNode &n )
const
61 QList<IndexedPointCloudNode> lst;
62 if ( !loadNodeHierarchy( n ) )
65 const int d = n.
d() + 1;
66 const int x = n.
x() * 2;
67 const int y = n.
y() * 2;
68 const int z = n.
z() * 2;
71 for (
int i = 0; i < 8; ++i )
73 int dx = i & 1, dy = !!( i & 2 ), dz = !!( i & 4 );
75 if ( loadNodeHierarchy( n2 ) )
81void QgsRemoteEptPointCloudIndex::load(
const QString &url )
85 QStringList splitUrl = url.split(
'/' );
87 mUrlFileNamePart = splitUrl.back();
89 mUrlDirectoryPart = splitUrl.join(
'/' );
91 QNetworkRequest nr( url );
103 mIsValid = loadSchema( reply.
content() );
108 std::unique_ptr<QgsPointCloudBlockRequest> blockRequest( asyncNodeData( n, request ) );
116 if ( !blockRequest->block() )
118 QgsDebugError( QStringLiteral(
"Error downloading node %1 data, error : %2 " ).arg( n.
toString(), blockRequest->errorStr() ) );
121 return blockRequest->block();
126 if ( !loadNodeHierarchy( n ) )
130 if ( mDataType == QLatin1String(
"binary" ) )
132 fileUrl = QStringLiteral(
"%1/ept-data/%2.bin" ).arg( mUrlDirectoryPart, n.
toString() );
134 else if ( mDataType == QLatin1String(
"zstandard" ) )
136 fileUrl = QStringLiteral(
"%1/ept-data/%2.zst" ).arg( mUrlDirectoryPart, n.
toString() );
138 else if ( mDataType == QLatin1String(
"laszip" ) )
140 fileUrl = QStringLiteral(
"%1/ept-data/%2.laz" ).arg( mUrlDirectoryPart, n.
toString() );
150 QgsPointCloudExpression filterExpression = mFilterExpression;
152 requestAttributes.
extend( attributes(), filterExpression.referencedAttributes() );
158 return loadNodeHierarchy( n );
163 mHierarchyMutex.lock();
164 bool found = mHierarchy.contains( nodeId );
165 mHierarchyMutex.unlock();
169 QVector<IndexedPointCloudNode> nodePathToRoot;
174 nodePathToRoot.push_back( currentNode );
177 while ( currentNode.
d() >= 0 );
180 for (
int i = nodePathToRoot.size() - 1; i >= 0 && !mHierarchy.contains( nodeId ); --i )
184 mHierarchyMutex.lock();
185 const bool foundInHierarchy = mHierarchy.contains( node );
186 const bool foundInHierarchyNodes = mHierarchyNodes.contains( node );
187 mHierarchyMutex.unlock();
188 if ( foundInHierarchy )
191 if ( !foundInHierarchyNodes )
194 const QString fileUrl = QStringLiteral(
"%1/ept-hierarchy/%2.json" ).arg( mUrlDirectoryPart, node.
toString() );
195 QNetworkRequest nr( fileUrl );
197 nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
198 nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
206 if ( reply->
error() != QNetworkReply::NoError )
208 QgsDebugError( QStringLiteral(
"Request failed: " ) + mUrl.toString() );
212 const QByteArray dataJsonH = reply->data();
213 QJsonParseError errH;
214 const QJsonDocument docH = QJsonDocument::fromJson( dataJsonH, &errH );
215 if ( errH.error != QJsonParseError::NoError )
217 QgsDebugMsgLevel( QStringLiteral(
"QJsonParseError when reading hierarchy from file %1" ).arg( fileUrl ), 2 );
221 const QJsonObject rootHObj = docH.object();
222 for (
auto it = rootHObj.constBegin(); it != rootHObj.constEnd(); ++it )
224 const QString nodeIdStr = it.key();
225 const int nodePointCount = it.value().toInt();
227 mHierarchyMutex.lock();
228 if ( nodePointCount >= 0 )
229 mHierarchy[nodeId] = nodePointCount;
230 else if ( nodePointCount == -1 )
231 mHierarchyNodes.insert( nodeId );
232 mHierarchyMutex.unlock();
236 mHierarchyMutex.lock();
237 found = mHierarchy.contains( nodeId );
238 mHierarchyMutex.unlock();
243bool QgsRemoteEptPointCloudIndex::isValid()
const
248void QgsRemoteEptPointCloudIndex::copyCommonProperties( QgsRemoteEptPointCloudIndex *destination )
const
250 QgsEptPointCloudIndex::copyCommonProperties( destination );
253 destination->mUrlDirectoryPart = mUrlDirectoryPart;
254 destination->mUrlFileNamePart = mUrlFileNamePart;
255 destination->mUrl = mUrl;
256 destination->mHierarchyNodes = mHierarchyNodes;
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.
static QgsTileDownloadManager * tileDownloadManager()
Returns the application's tile download manager, used for download of map tiles when rendering.
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(), post(), head() or put() request has been mad...
Base class for handling loading QgsPointCloudBlock asynchronously from a remote EPT dataset.
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
QByteArray content() const
Returns the reply content.
QNetworkReply::NetworkError error() const
Returns the reply's error message, or QNetworkReply::NoError if no error was encountered.
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 QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
#define QgsSetRequestInitiatorClass(request, _class)