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)