Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgspointcloudindex.h 3 : : -------------------- 4 : : begin : October 2020 5 : : copyright : (C) 2020 by Peter Petrik 6 : : email : zilolv at gmail dot com 7 : : ***************************************************************************/ 8 : : 9 : : /*************************************************************************** 10 : : * * 11 : : * This program is free software; you can redistribute it and/or modify * 12 : : * it under the terms of the GNU General Public License as published by * 13 : : * the Free Software Foundation; either version 2 of the License, or * 14 : : * (at your option) any later version. * 15 : : * * 16 : : ***************************************************************************/ 17 : : 18 : : #ifndef QGSPOINTCLOUDINDEX_H 19 : : #define QGSPOINTCLOUDINDEX_H 20 : : 21 : : #include <QObject> 22 : : #include <QString> 23 : : #include <QHash> 24 : : #include <QStringList> 25 : : #include <QVector> 26 : : #include <QList> 27 : : 28 : : #include "qgis_core.h" 29 : : #include "qgsrectangle.h" 30 : : #include "qgsvector3d.h" 31 : : #include "qgis_sip.h" 32 : : #include "qgspointcloudblock.h" 33 : : #include "qgsrange.h" 34 : : #include "qgspointcloudattribute.h" 35 : : #include "qgsstatisticalsummary.h" 36 : : 37 : : #define SIP_NO_FILE 38 : : 39 : : class QgsPointCloudRequest; 40 : : class QgsPointCloudAttributeCollection; 41 : : class QgsCoordinateReferenceSystem; 42 : : class QgsPointCloudBlockRequest; 43 : : 44 : : /** 45 : : * \ingroup core 46 : : * 47 : : * \brief Represents a indexed point cloud node in octree 48 : : * 49 : : * \note The API is considered EXPERIMENTAL and can be changed without a notice 50 : : * 51 : : * \since QGIS 3.18 52 : : */ 53 : : class CORE_EXPORT IndexedPointCloudNode 54 : : { 55 : : public: 56 : : //! Constructs invalid node 57 : : IndexedPointCloudNode(); 58 : : //! Constructs valid node 59 : : IndexedPointCloudNode( int _d, int _x, int _y, int _z ); 60 : : 61 : : //! Returns whether node is valid 62 : : bool isValid() const { return mD >= 0; } 63 : : 64 : : //! Compares nodes 65 : 0 : bool operator==( IndexedPointCloudNode other ) const 66 : : { 67 : 0 : return mD == other.d() && mX == other.x() && mY == other.y() && mZ == other.z(); 68 : : } 69 : : 70 : : /** 71 : : * Returns the parent of the node 72 : : * \since QGIS 3.20 73 : : */ 74 : : IndexedPointCloudNode parentNode() const; 75 : : 76 : : //! Creates node from string 77 : : static IndexedPointCloudNode fromString( const QString &str ); 78 : : 79 : : //! Encode node to string 80 : : QString toString() const; 81 : : 82 : : //! Returns d 83 : : int d() const; 84 : : 85 : : //! Returns x 86 : : int x() const; 87 : : 88 : : //! Returns y 89 : : int y() const; 90 : : 91 : : //! Returns z 92 : : int z() const; 93 : : 94 : : private: 95 : : int mD = -1, mX = -1, mY = -1, mZ = -1; 96 : : }; 97 : : 98 : : Q_DECLARE_TYPEINFO( IndexedPointCloudNode, Q_PRIMITIVE_TYPE ); 99 : : 100 : : //! Hash function for indexed nodes 101 : : CORE_EXPORT uint qHash( IndexedPointCloudNode id ); 102 : : 103 : : /** 104 : : * \ingroup core 105 : : * 106 : : * \brief Represents packaged data bounds 107 : : * 108 : : * \note The API is considered EXPERIMENTAL and can be changed without a notice 109 : : * 110 : : * \since QGIS 3.18 111 : : */ 112 : : class CORE_EXPORT QgsPointCloudDataBounds 113 : : { 114 : : public: 115 : : //! Constructs invalid bounds 116 : : QgsPointCloudDataBounds(); 117 : : //! Constructs bounds 118 : : QgsPointCloudDataBounds( qint32 xmin, qint32 ymin, qint32 zmin, qint32 xmax, qint32 ymax, qint32 zmax ); 119 : : 120 : : //! Returns x min 121 : : qint32 xMin() const; 122 : : 123 : : //! Returns y min 124 : : qint32 yMin() const; 125 : : 126 : : //! Returns z min 127 : : qint32 zMin() const; 128 : : 129 : : //! Returns x max 130 : : qint32 xMax() const; 131 : : 132 : : //! Returns y max 133 : : qint32 yMax() const; 134 : : 135 : : //! Returns z max 136 : : qint32 zMax() const; 137 : : 138 : : //! Returns 2D rectangle in map coordinates 139 : : QgsRectangle mapExtent( const QgsVector3D &offset, const QgsVector3D &scale ) const; 140 : : 141 : : //! Returns the z range, applying the specified \a offset and \a scale. 142 : : QgsDoubleRange zRange( const QgsVector3D &offset, const QgsVector3D &scale ) const; 143 : : 144 : : private: 145 : : qint32 mXMin, mYMin, mZMin, mXMax, mYMax, mZMax; 146 : : }; 147 : : 148 : : /** 149 : : * \ingroup core 150 : : * 151 : : * \brief Represents a indexed point clouds data in octree 152 : : * 153 : : * \note The API is considered EXPERIMENTAL and can be changed without a notice 154 : : * 155 : : * \since QGIS 3.18 156 : : */ 157 : : class CORE_EXPORT QgsPointCloudIndex: public QObject 158 : : { 159 : : Q_OBJECT 160 : : public: 161 : : //! The access type of the data, local is for local files and remote for remote files (over HTTP) 162 : : enum AccessType 163 : : { 164 : : Local, //! Local means the source is a local file on the machine 165 : : Remote //! Remote means it's loaded through a protocol like HTTP 166 : : }; 167 : : 168 : : //! Constructs index 169 : : explicit QgsPointCloudIndex(); 170 : : ~QgsPointCloudIndex(); 171 : : 172 : : //! Loads the index from the file 173 : : virtual void load( const QString &fileName ) = 0; 174 : : 175 : : //! Returns whether index is loaded and valid 176 : : virtual bool isValid() const = 0; 177 : : 178 : : /** 179 : : * Returns the access type of the data 180 : : * If the access type is Remote, data will be fetched from an HTTP server either synchronously or asynchronously 181 : : * If the access type is local, the data is stored locally as a file and will only be fetch synchronously ( blocking request with nodeData only ) 182 : : * \note Always make sure to check before trying to use asyncNodeData since it is not supported in the case of local access type 183 : : */ 184 : : virtual AccessType accessType() const = 0; 185 : : 186 : : //! Returns the coordinate reference system of the point cloud index 187 : : virtual QgsCoordinateReferenceSystem crs() const = 0; 188 : : //! Returns the number of points in the point cloud 189 : : virtual qint64 pointCount() const = 0; 190 : : //! Returns the statistic \a statistic of \a attribute 191 : : virtual QVariant metadataStatistic( const QString &attribute, QgsStatisticalSummary::Statistic statistic ) const = 0; 192 : : //! Returns the classes of \a attribute 193 : : virtual QVariantList metadataClasses( const QString &attribute ) const = 0; 194 : : //! Returns the statistic \a statistic of the class \a value of the attribute \a attribute 195 : : virtual QVariant metadataClassStatistic( const QString &attribute, const QVariant &value, QgsStatisticalSummary::Statistic statistic ) const = 0; 196 : : //! Returns the original metadata map 197 : : virtual QVariantMap originalMetadata() const = 0; 198 : : 199 : : //! Returns root node of the index 200 : 0 : IndexedPointCloudNode root() { return IndexedPointCloudNode( 0, 0, 0, 0 ); } 201 : : 202 : : //! Returns whether the octree contain given node 203 : : virtual bool hasNode( const IndexedPointCloudNode &n ) const { return mHierarchy.contains( n ); } 204 : : 205 : : //! Returns all children of node 206 : : virtual QList<IndexedPointCloudNode> nodeChildren( const IndexedPointCloudNode &n ) const; 207 : : 208 : : //! Returns all attributes that are stored in the file 209 : : QgsPointCloudAttributeCollection attributes() const; 210 : : 211 : : /** 212 : : * Returns node data block 213 : : * 214 : : * e.g. positions (needs to be scaled and offset applied to get coordinates) or 215 : : * classification, intensity or custom attributes 216 : : * 217 : : * It is caller responsibility to free the block. 218 : : * 219 : : * May return nullptr in case the node is not present or any other problem with loading 220 : : */ 221 : : virtual QgsPointCloudBlock *nodeData( const IndexedPointCloudNode &n, const QgsPointCloudRequest &request ) = 0; 222 : : 223 : : /** 224 : : * Returns a handle responsible for loading a node data block 225 : : * 226 : : * e.g. positions (needs to be scaled and offset applied to get coordinates) or 227 : : * classification, intensity or custom attributes 228 : : * 229 : : * It is caller responsibility to free the handle and the block issued by the handle if the loading succeeds. 230 : : * 231 : : * May return nullptr in case the node is not present or any other problem with loading 232 : : */ 233 : : virtual QgsPointCloudBlockRequest *asyncNodeData( const IndexedPointCloudNode &n, const QgsPointCloudRequest &request ) = 0; 234 : : 235 : : //! Returns extent of the data 236 : 0 : QgsRectangle extent() const { return mExtent; } 237 : : 238 : : //! Returns z min 239 : : double zMin() const { return mZMin; } 240 : : //! Returns z max 241 : : double zMax() const { return mZMax; } 242 : : 243 : : //! Returns bounds of particular \a node 244 : : QgsPointCloudDataBounds nodeBounds( const IndexedPointCloudNode &node ) const; 245 : : 246 : : /** 247 : : * Returns the extent of a \a node in map coordinates. 248 : : * 249 : : * \see nodeZRange() 250 : : */ 251 : : QgsRectangle nodeMapExtent( const IndexedPointCloudNode &node ) const; 252 : : 253 : : /** 254 : : * Returns the z range of a \a node. 255 : : * 256 : : * \see nodeMapExtent() 257 : : */ 258 : : QgsDoubleRange nodeZRange( const IndexedPointCloudNode &node ) const; 259 : : 260 : : //! Returns node's error in map units (used to determine in whether the node has enough detail for the current view) 261 : : float nodeError( const IndexedPointCloudNode &n ) const; 262 : : 263 : : //! Returns scale 264 : : QgsVector3D scale() const; 265 : : 266 : : //! Returns offset 267 : : QgsVector3D offset() const; 268 : : 269 : : /** 270 : : * Returns the number of points in one direction in a single node. 271 : : */ 272 : : int span() const; 273 : : 274 : : /** 275 : : * Returns the number of poiny of indexed point cloud node \a n 276 : : */ 277 : : int nodePointCount( const IndexedPointCloudNode &n ); 278 : : 279 : : protected: //TODO private 280 : : //! Sets native attributes of the data 281 : : void setAttributes( const QgsPointCloudAttributeCollection &attributes ); 282 : : 283 : : QgsRectangle mExtent; //!< 2D extent of data 284 : : double mZMin = 0, mZMax = 0; //!< Vertical extent of data 285 : : 286 : : mutable QHash<IndexedPointCloudNode, int> mHierarchy; //!< Data hierarchy 287 : : QgsVector3D mScale; //!< Scale of our int32 coordinates compared to CRS coords 288 : : QgsVector3D mOffset; //!< Offset of our int32 coordinates compared to CRS coords 289 : : QgsPointCloudDataBounds mRootBounds; //!< Bounds of the root node's cube (in int32 coordinates) 290 : : QgsPointCloudAttributeCollection mAttributes; //! All native attributes stored in the file 291 : : int mSpan; //!< Number of points in one direction in a single node 292 : : }; 293 : : 294 : : #endif // QGSPOINTCLOUDINDEX_H