Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgspointclouddataprovider.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 QGSPOINTCLOUDDATAPROVIDER_H
19 : : #define QGSPOINTCLOUDDATAPROVIDER_H
20 : :
21 : : #include "qgis_core.h"
22 : : #include "qgsdataprovider.h"
23 : : #include "qgspointcloudattribute.h"
24 : : #include "qgsstatisticalsummary.h"
25 : : #include "qgspointcloudindex.h"
26 : : #include "qgspoint.h"
27 : : #include "qgsray3d.h"
28 : : #include <memory>
29 : :
30 : : class IndexedPointCloudNode;
31 : : class QgsPointCloudIndex;
32 : : class QgsPointCloudRenderer;
33 : : class QgsGeometry;
34 : :
35 : : /**
36 : : * \ingroup core
37 : : * \brief Base class for providing data for QgsPointCloudLayer
38 : : *
39 : : * Responsible for reading native point cloud data and returning the indexed data.
40 : : *
41 : : * \note The API is considered EXPERIMENTAL and can be changed without a notice
42 : : *
43 : : * \since QGIS 3.18
44 : : */
45 : : class CORE_EXPORT QgsPointCloudDataProvider: public QgsDataProvider
46 : : {
47 : : Q_OBJECT
48 : : public:
49 : :
50 : : /**
51 : : * Capabilities that providers may implement.
52 : : */
53 : : enum Capability
54 : : {
55 : : NoCapabilities = 0, //!< Provider has no capabilities
56 : : ReadLayerMetadata = 1 << 0, //!< Provider can read layer metadata from data store.
57 : : WriteLayerMetadata = 1 << 1, //!< Provider can write layer metadata to the data store. See QgsDataProvider::writeLayerMetadata()
58 : : CreateRenderer = 1 << 2, //!< Provider can create 2D renderers using backend-specific formatting information. See QgsPointCloudDataProvider::createRenderer().
59 : : };
60 : :
61 : : Q_DECLARE_FLAGS( Capabilities, Capability )
62 : :
63 : : /**
64 : : * Point cloud index state
65 : : */
66 : : enum PointCloudIndexGenerationState
67 : : {
68 : : NotIndexed = 0, //!< Provider has no index available
69 : : Indexing = 1 << 0, //!< Provider try to index the source data
70 : : Indexed = 1 << 1 //!< The index is ready to be used
71 : : };
72 : :
73 : : //! Ctor
74 : : QgsPointCloudDataProvider( const QString &uri,
75 : : const QgsDataProvider::ProviderOptions &providerOptions,
76 : : QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() );
77 : :
78 : : ~QgsPointCloudDataProvider() override;
79 : :
80 : : #ifndef SIP_RUN
81 : :
82 : : /**
83 : : * Returns the list of points of the point cloud according to a zoom level
84 : : * defined by \a maxError (in layer coordinates), an extent \a geometry in the 2D plane
85 : : * and a range \a extentZRange for z values. The function will try to limit
86 : : * the number of points returned to \a pointsLimit points
87 : : *
88 : : * \a maxErrorPixels : maximum accepted error factor in pixels
89 : : *
90 : : * \note this function does not handle elevation properties and you need to
91 : : * change elevation coordinates yourself after returning from the function
92 : : */
93 : : QVector<QVariantMap> identify( double maxError, const QgsGeometry &extentGeometry, const QgsDoubleRange &extentZRange = QgsDoubleRange(), int pointsLimit = 1000 );
94 : : #else
95 : :
96 : : /**
97 : : * Returns the list of points of the point cloud according to a zoom level
98 : : * defined by \a maxError (in layer coordinates), an extent \a geometry in the 2D plane
99 : : * and a range \a extentZRange for z values. The function will try to limit
100 : : * the number of points returned to \a pointsLimit points
101 : : *
102 : : * \a maxErrorPixels : maximum accepted error factor in pixels
103 : : *
104 : : * \note this function does not handle elevation properties and you need to
105 : : * change elevation coordinates yourself after returning from the function
106 : : */
107 : : SIP_PYLIST identify( float maxErrorInMapCoords, QgsGeometry extentGeometry, const QgsDoubleRange extentZRange = QgsDoubleRange(), int pointsLimit = 1000 );
108 : : % MethodCode
109 : : {
110 : : QVector<QMap<QString, QVariant>> res = sipCpp->identify( a0, *a1, *a2, a3 );
111 : : sipRes = PyList_New( res.size() );
112 : : for ( int i = 0; i < res.size(); ++i )
113 : : {
114 : : PyObject *dict = PyDict_New();
115 : : for ( QString key : res[i].keys() )
116 : : {
117 : : PyObject *keyObj = sipConvertFromNewType( new QString( key ), sipType_QString, Py_None );
118 : : PyObject *valObj = sipConvertFromNewType( new QVariant( res[i][key] ), sipType_QVariant, Py_None );
119 : : PyDict_SetItem( dict, keyObj, valObj );
120 : : }
121 : : PyList_SET_ITEM( sipRes, i, dict );
122 : : }
123 : : }
124 : : % End
125 : : #endif
126 : :
127 : : /**
128 : : * Returns flags containing the supported capabilities for the data provider.
129 : : */
130 : : virtual QgsPointCloudDataProvider::Capabilities capabilities() const;
131 : :
132 : : /**
133 : : * Returns the attributes available from this data provider.
134 : : * May return empty collection until pointCloudIndexLoaded() is emitted
135 : : */
136 : : virtual QgsPointCloudAttributeCollection attributes() const = 0;
137 : :
138 : : /**
139 : : * Triggers loading of the point cloud index
140 : : *
141 : : * \sa index()
142 : : */
143 : : virtual void loadIndex( ) = 0;
144 : :
145 : : /**
146 : : * Triggers generation of the point cloud index
147 : : *
148 : : * emits indexGenerationStateChanged()
149 : : *
150 : : * \sa index()
151 : : */
152 : : virtual void generateIndex( ) = 0;
153 : :
154 : :
155 : : /**
156 : : * Gets the current index generation state
157 : : */
158 : : virtual PointCloudIndexGenerationState indexingState( ) = 0;
159 : :
160 : : /**
161 : : * Returns the point cloud index associated with the provider.
162 : : *
163 : : * Can be nullptr (e.g. the index is being created)
164 : : *
165 : : * \note Not available in Python bindings
166 : : */
167 : 0 : virtual QgsPointCloudIndex *index() const SIP_SKIP {return nullptr;}
168 : :
169 : : /**
170 : : * Returns whether provider has index which is valid
171 : : */
172 : : bool hasValidIndex() const;
173 : :
174 : : /**
175 : : * Returns the total number of points available in the dataset.
176 : : */
177 : : virtual int pointCount() const = 0;
178 : :
179 : : /**
180 : : * Returns the polygon bounds of the layer. The CRS of the returned geometry will match the provider's crs().
181 : : *
182 : : * This method will return the best approximation for the actual bounds of points contained in the
183 : : * dataset available from the provider's metadata. This may match the bounding box rectangle returned
184 : : * by extent(), or for some datasets a "convex hull" style polygon representing a more precise bounds
185 : : * will be returned.
186 : : *
187 : : * This method will not attempt to calculate the data bounds, rather it will return only whatever precomputed bounds
188 : : * are included in the data source's metadata.
189 : : */
190 : : virtual QgsGeometry polygonBounds() const;
191 : :
192 : : /**
193 : : * Returns a representation of the original metadata included in a point cloud dataset.
194 : : *
195 : : * This is a free-form dictionary of values, the contents and structure of which will vary by provider and
196 : : * dataset.
197 : : */
198 : : virtual QVariantMap originalMetadata() const;
199 : :
200 : : /**
201 : : * Creates a new 2D point cloud renderer, using provider backend specific information.
202 : : *
203 : : * The \a configuration map can be used to pass provider-specific configuration maps to the provider to
204 : : * allow customization of the returned renderer. Support and format of \a configuration varies by provider.
205 : : *
206 : : * When called with an empty \a configuration map the provider's default renderer will be returned.
207 : : *
208 : : * This method returns a new renderer and the caller takes ownership of the returned object.
209 : : *
210 : : * Only providers which report the CreateRenderer capability will return a 2D renderer. Other
211 : : * providers will return NULLPTR.
212 : : */
213 : : virtual QgsPointCloudRenderer *createRenderer( const QVariantMap &configuration = QVariantMap() ) const SIP_FACTORY;
214 : : #ifndef SIP_RUN
215 : :
216 : : /**
217 : : * Returns a statistic for the specified \a attribute, taken only from the metadata of the point cloud
218 : : * data source.
219 : : *
220 : : * This method will not perform any statistical calculations, rather it will return only precomputed attribute
221 : : * statistics which are included in the data source's metadata. Not all data sources include this information
222 : : * in the metadata, and even for sources with statistical metadata only some \a statistic values may be available.
223 : : *
224 : : * If no matching precalculated statistic is available then an invalid variant will be returned.
225 : : */
226 : : virtual QVariant metadataStatistic( const QString &attribute, QgsStatisticalSummary::Statistic statistic ) const;
227 : : #else
228 : :
229 : : /**
230 : : * Returns a statistic for the specified \a attribute, taken only from the metadata of the point cloud
231 : : * data source.
232 : : *
233 : : * This method will not perform any statistical calculations, rather it will return only precomputed attribute
234 : : * statistics which are included in the data source's metadata. Not all data sources include this information
235 : : * in the metadata, and even for sources with statistical metadata only some \a statistic values may be available.
236 : : *
237 : : * \throws ValueError if no matching precalculated statistic is available for the attribute.
238 : : */
239 : : SIP_PYOBJECT metadataStatistic( const QString &attribute, QgsStatisticalSummary::Statistic statistic ) const;
240 : : % MethodCode
241 : : {
242 : : const QVariant res = sipCpp->metadataStatistic( *a0, a1 );
243 : : if ( !res.isValid() )
244 : : {
245 : : PyErr_SetString( PyExc_ValueError, QStringLiteral( "Statistic is not available" ).toUtf8().constData() );
246 : : sipIsErr = 1;
247 : : }
248 : : else
249 : : {
250 : : QVariant *v = new QVariant( res );
251 : : sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
252 : : }
253 : : }
254 : : % End
255 : : #endif
256 : :
257 : : /**
258 : : * Returns a list of existing classes which are present for the specified \a attribute, taken only from the
259 : : * metadata of the point cloud data source.
260 : : *
261 : : * This method will not perform any classification or scan for available classes, rather it will return only
262 : : * precomputed classes which are included in the data source's metadata. Not all data sources include this information
263 : : * in the metadata.
264 : : */
265 : : virtual QVariantList metadataClasses( const QString &attribute ) const;
266 : :
267 : :
268 : : #ifndef SIP_RUN
269 : :
270 : : /**
271 : : * Returns a statistic for one class \a value from the specified \a attribute, taken only from the metadata of the point cloud
272 : : * data source.
273 : : *
274 : : * This method will not perform any statistical calculations, rather it will return only precomputed class
275 : : * statistics which are included in the data source's metadata. Not all data sources include this information
276 : : * in the metadata, and even for sources with statistical metadata only some \a statistic values may be available.
277 : : *
278 : : * If no matching precalculated statistic is available then an invalid variant will be returned.
279 : : */
280 : : virtual QVariant metadataClassStatistic( const QString &attribute, const QVariant &value, QgsStatisticalSummary::Statistic statistic ) const;
281 : : #else
282 : :
283 : : /**
284 : : * Returns a statistic for one class \a value from the specified \a attribute, taken only from the metadata of the point cloud
285 : : * data source.
286 : : * This method will not perform any statistical calculations, rather it will return only precomputed class
287 : : * statistics which are included in the data source's metadata. Not all data sources include this information
288 : : * in the metadata, and even for sources with statistical metadata only some \a statistic values may be available.
289 : : *
290 : : * \throws ValueError if no matching precalculated statistic is available for the attribute.
291 : : */
292 : : SIP_PYOBJECT metadataClassStatistic( const QString &attribute, const QVariant &value, QgsStatisticalSummary::Statistic statistic ) const;
293 : : % MethodCode
294 : : {
295 : : const QVariant res = sipCpp->metadataClassStatistic( *a0, *a1, a2 );
296 : : if ( !res.isValid() )
297 : : {
298 : : PyErr_SetString( PyExc_ValueError, QStringLiteral( "Statistic is not available" ).toUtf8().constData() );
299 : : sipIsErr = 1;
300 : : }
301 : : else
302 : : {
303 : : QVariant *v = new QVariant( res );
304 : : sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
305 : : }
306 : : }
307 : : % End
308 : : #endif
309 : :
310 : : /**
311 : : * Returns the map of LAS classification code to untranslated string value, corresponding to the ASPRS Standard
312 : : * Lidar Point Classes.
313 : : *
314 : : * \see translatedLasClassificationCodes()
315 : : */
316 : : static QMap< int, QString > lasClassificationCodes();
317 : :
318 : : /**
319 : : * Returns the map of LAS classification code to translated string value, corresponding to the ASPRS Standard
320 : : * Lidar Point Classes.
321 : : *
322 : : * \see lasClassificationCodes()
323 : : */
324 : : static QMap< int, QString > translatedLasClassificationCodes();
325 : :
326 : : /**
327 : : * Returns the map of LAS data format ID to untranslated string value.
328 : : *
329 : : * \see translatedDataFormatIds()
330 : : */
331 : : static QMap< int, QString > dataFormatIds();
332 : :
333 : : /**
334 : : * Returns the map of LAS data format ID to translated string value.
335 : : *
336 : : * \see dataFormatIds()
337 : : */
338 : : static QMap< int, QString > translatedDataFormatIds();
339 : :
340 : : signals:
341 : :
342 : : /**
343 : : * Emitted when point cloud generation state is changed
344 : : */
345 : : void indexGenerationStateChanged( PointCloudIndexGenerationState state );
346 : :
347 : : private:
348 : : QVector<IndexedPointCloudNode> traverseTree( const QgsPointCloudIndex *pc, IndexedPointCloudNode n, double maxError, double nodeError, const QgsGeometry &extentGeometry, const QgsDoubleRange &extentZRange );
349 : : };
350 : :
351 : : #endif // QGSMESHDATAPROVIDER_H
|