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 std::unique_ptr<QgsPointCloudBlock> block = blockRequest->takeBlock();
119 QgsDebugError( QStringLiteral(
"Error downloading node %1 data, error : %2 " ).arg( n.
toString(), blockRequest->errorStr() ) );
127 if ( !loadNodeHierarchy( n ) )
131 if ( mDataType == QLatin1String(
"binary" ) )
133 fileUrl = QStringLiteral(
"%1/ept-data/%2.bin" ).arg( mUrlDirectoryPart, n.
toString() );
135 else if ( mDataType == QLatin1String(
"zstandard" ) )
137 fileUrl = QStringLiteral(
"%1/ept-data/%2.zst" ).arg( mUrlDirectoryPart, n.
toString() );
139 else if ( mDataType == QLatin1String(
"laszip" ) )
141 fileUrl = QStringLiteral(
"%1/ept-data/%2.laz" ).arg( mUrlDirectoryPart, n.
toString() );
151 QgsPointCloudExpression filterExpression = mFilterExpression;
153 requestAttributes.
extend( attributes(), filterExpression.referencedAttributes() );
159 return loadNodeHierarchy( n );
164 mHierarchyMutex.lock();
165 bool found = mHierarchy.contains( nodeId );
166 mHierarchyMutex.unlock();
170 QVector<IndexedPointCloudNode> nodePathToRoot;
175 nodePathToRoot.push_back( currentNode );
178 while ( currentNode.
d() >= 0 );
181 for (
int i = nodePathToRoot.size() - 1; i >= 0 && !mHierarchy.contains( nodeId ); --i )
185 mHierarchyMutex.lock();
186 const bool foundInHierarchy = mHierarchy.contains( node );
187 const bool foundInHierarchyNodes = mHierarchyNodes.contains( node );
188 mHierarchyMutex.unlock();
189 if ( foundInHierarchy )
192 if ( !foundInHierarchyNodes )
195 const QString fileUrl = QStringLiteral(
"%1/ept-hierarchy/%2.json" ).arg( mUrlDirectoryPart, node.
toString() );
196 QNetworkRequest nr( fileUrl );
198 nr.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
199 nr.setAttribute( QNetworkRequest::CacheSaveControlAttribute,
true );
207 if ( reply->
error() != QNetworkReply::NoError )
209 QgsDebugError( QStringLiteral(
"Request failed: " ) + mUrl.toString() );
213 const QByteArray dataJsonH = reply->data();
214 QJsonParseError errH;
215 const QJsonDocument docH = QJsonDocument::fromJson( dataJsonH, &errH );
216 if ( errH.error != QJsonParseError::NoError )
218 QgsDebugMsgLevel( QStringLiteral(
"QJsonParseError when reading hierarchy from file %1" ).arg( fileUrl ), 2 );
222 const QJsonObject rootHObj = docH.object();
223 for (
auto it = rootHObj.constBegin(); it != rootHObj.constEnd(); ++it )
225 const QString nodeIdStr = it.key();
226 const int nodePointCount = it.value().toInt();
228 mHierarchyMutex.lock();
229 if ( nodePointCount >= 0 )
230 mHierarchy[nodeId] = nodePointCount;
231 else if ( nodePointCount == -1 )
232 mHierarchyNodes.insert( nodeId );
233 mHierarchyMutex.unlock();
237 mHierarchyMutex.lock();
238 found = mHierarchy.contains( nodeId );
239 mHierarchyMutex.unlock();
244bool QgsRemoteEptPointCloudIndex::isValid()
const
249void QgsRemoteEptPointCloudIndex::copyCommonProperties( QgsRemoteEptPointCloudIndex *destination )
const
251 QgsEptPointCloudIndex::copyCommonProperties( destination );
254 destination->mUrlDirectoryPart = mUrlDirectoryPart;
255 destination->mUrlFileNamePart = mUrlFileNamePart;
256 destination->mUrl = mUrl;
257 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.
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)