Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: GDALRasterAttributeTable class declarations.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef GDAL_RAT_H_INCLUDED
14 : #define GDAL_RAT_H_INCLUDED
15 :
16 : #if !defined(GDAL_COMPILATION) && \
17 : !defined(GDAL_RAT_SKIP_OTHER_GDAL_HEADERS) && !defined(GDAL_4_0_COMPAT)
18 :
19 : #include "cpl_minixml.h"
20 : #include "gdal_priv.h"
21 :
22 : #else
23 :
24 : #include "cpl_port.h"
25 : #include "cpl_error.h"
26 : #include "cpl_string.h"
27 : #include "gdal.h"
28 :
29 : #endif
30 :
31 : #include <memory>
32 : #include <vector>
33 :
34 : class GDALColorTable;
35 :
36 : // Clone and Serialize are allowed to fail if GetRowCount()*GetColCount()
37 : // greater than this number
38 : #define RAT_MAX_ELEM_FOR_CLONE 1000000
39 :
40 : /************************************************************************/
41 : /* GDALRasterAttributeTable */
42 : /************************************************************************/
43 :
44 : //! Raster Attribute Table interface.
45 : class GDALDefaultRasterAttributeTable;
46 :
47 1238 : class CPL_DLL GDALRasterAttributeTable
48 : {
49 : public:
50 : virtual ~GDALRasterAttributeTable();
51 : /**
52 : * \brief Copy Raster Attribute Table
53 : *
54 : * Creates a new copy of an existing raster attribute table. The new copy
55 : * becomes the responsibility of the caller to destroy.
56 : * May fail (return nullptr) if the attribute table is too large to clone
57 : * (GetRowCount() * GetColCount() > RAT_MAX_ELEM_FOR_CLONE)
58 : *
59 : * This method is the same as the C function GDALRATClone().
60 : *
61 : * @return new copy of the RAT as an in-memory implementation.
62 : */
63 : virtual GDALRasterAttributeTable *Clone() const = 0;
64 :
65 : /**
66 : * \brief Fetch table column count.
67 : *
68 : * This method is the same as the C function GDALRATGetColumnCount().
69 : *
70 : * @return the number of columns.
71 : */
72 : virtual int GetColumnCount() const = 0;
73 :
74 : /**
75 : * \brief Fetch name of indicated column.
76 : *
77 : * This method is the same as the C function GDALRATGetNameOfCol().
78 : *
79 : * @param iCol the column index (zero based).
80 : *
81 : * @return the column name or an empty string for invalid column numbers.
82 : */
83 : virtual const char *GetNameOfCol(int iCol) const = 0;
84 :
85 : /**
86 : * \brief Fetch column usage value.
87 : *
88 : * This method is the same as the C function GDALRATGetUsageOfCol().
89 : *
90 : * @param iCol the column index (zero based).
91 : *
92 : * @return the column usage, or GFU_Generic for improper column numbers.
93 : */
94 : virtual GDALRATFieldUsage GetUsageOfCol(int iCol) const = 0;
95 :
96 : /**
97 : * \brief Fetch column type.
98 : *
99 : * This method is the same as the C function GDALRATGetTypeOfCol().
100 : *
101 : * @param iCol the column index (zero based).
102 : *
103 : * @return column type or GFT_Integer if the column index is illegal.
104 : */
105 : virtual GDALRATFieldType GetTypeOfCol(int iCol) const = 0;
106 :
107 : /**
108 : * \brief Fetch column index for given usage.
109 : *
110 : * Returns the index of the first column of the requested usage type, or -1
111 : * if no match is found.
112 : *
113 : * This method is the same as the C function GDALRATGetUsageOfCol().
114 : *
115 : * @param eUsage usage type to search for.
116 : *
117 : * @return column index, or -1 on failure.
118 : */
119 : virtual int GetColOfUsage(GDALRATFieldUsage eUsage) const = 0;
120 :
121 : /**
122 : * \brief Fetch row count.
123 : *
124 : * This method is the same as the C function GDALRATGetRowCount().
125 : *
126 : * @return the number of rows.
127 : */
128 : virtual int GetRowCount() const = 0;
129 :
130 : /**
131 : * \brief Fetch field value as a string.
132 : *
133 : * The value of the requested column in the requested row is returned
134 : * as a string. This method is nominally called on fields of type GFT_String,
135 : * but it can be called on fields of other types as well.
136 : * If the field is numeric, it is formatted as a string
137 : * using default rules, so some precision may be lost.
138 : *
139 : * The returned string is temporary and cannot be expected to be
140 : * available after the next GDAL call.
141 : *
142 : * This method is the same as the C function GDALRATGetValueAsString().
143 : *
144 : * @param iRow row to fetch (zero based).
145 : * @param iField column to fetch (zero based).
146 : *
147 : * @return field value.
148 : */
149 : virtual const char *GetValueAsString(int iRow, int iField) const = 0;
150 :
151 : /**
152 : * \brief Fetch field value as a integer.
153 : *
154 : * The value of the requested column in the requested row is returned
155 : * as an integer. This method is nominally called on fields of type
156 : * GFT_Integer, but it can be called on fields of other types as well.
157 : * Non-integer fields will be converted to integer with the possibility of
158 : * data loss.
159 : *
160 : * This method is the same as the C function GDALRATGetValueAsInt().
161 : *
162 : * @param iRow row to fetch (zero based).
163 : * @param iField column to fetch (zero based).
164 : *
165 : * @return field value
166 : */
167 : virtual int GetValueAsInt(int iRow, int iField) const = 0;
168 :
169 : /**
170 : * \brief Fetch field value as a double.
171 : *
172 : * The value of the requested column in the requested row is returned
173 : * as a double. This method is nominally called on fields of type
174 : * GFT_Real, but it can be called on fields of other types as well.
175 : * Non double fields will be converted to double with
176 : * the possibility of data loss.
177 : *
178 : * This method is the same as the C function GDALRATGetValueAsDouble().
179 : *
180 : * @param iRow row to fetch (zero based).
181 : * @param iField column to fetch (zero based).
182 : *
183 : * @return field value
184 : */
185 : virtual double GetValueAsDouble(int iRow, int iField) const = 0;
186 :
187 : /**
188 : * \brief Fetch field value as a boolean.
189 : *
190 : * The value of the requested column in the requested row is returned
191 : * as a boolean. This method is nominally called on fields of type
192 : * GFT_Boolean, but it can be called on fields of other types as well.
193 : * Non boolean fields will be converted to boolean with the possibility of
194 : * data loss.
195 : *
196 : * This method is the same as the C function GDALRATGetValueAsBoolean().
197 : *
198 : * @param iRow row to fetch (zero based).
199 : * @param iField column to fetch (zero based).
200 : *
201 : * @return field value
202 : * @since 3.12
203 : */
204 : virtual bool GetValueAsBoolean(int iRow, int iField) const = 0;
205 :
206 : /**
207 : * \brief Fetch field value as a datetime.
208 : *
209 : * The value of the requested column in the requested row is returned
210 : * as a datetime. Besides being called on a GFT_DateTime field, it
211 : * is also possible to call this method on a string field that contains a
212 : * ISO-8601 encoded datetime.
213 : *
214 : * This method is the same as the C function GDALRATGetValueAsDateTime().
215 : *
216 : * @param iRow row to fetch (zero based).
217 : * @param iField column to fetch (zero based).
218 : *
219 : * @return field value
220 : * @since 3.12
221 : */
222 : virtual GDALRATDateTime GetValueAsDateTime(int iRow, int iField) const = 0;
223 :
224 : /**
225 : * \brief Fetch field value as a WKB geometry.
226 : *
227 : * The value of the requested column in the requested row is returned
228 : * as a WKB geometry. Besides being called on a GFT_WKBGeometry field, it
229 : * is also possible to call this method on a string field that contains a WKT
230 : * encoded geometry.
231 : *
232 : * The returned pointer may be invalidated by a following call to a method
233 : * of this GDALRasterAttributeTable instance.
234 : *
235 : * This method is the same as the C function GDALRATGetValueAsWKBGeometry().
236 : *
237 : * @param iRow row to fetch (zero based).
238 : * @param iField column to fetch (zero based).
239 : * @param[out] nWKBSize Number of bytes of the returned pointer
240 : * @return field value, or nullptr
241 : * @since 3.12
242 : */
243 : virtual const GByte *GetValueAsWKBGeometry(int iRow, int iField,
244 : size_t &nWKBSize) const = 0;
245 :
246 : /**
247 : * \brief Set field value from string.
248 : *
249 : * The indicated field (column) on the indicated row is set from the
250 : * passed value. This method is nominally called on fields of type
251 : * GFT_String, but it can be called on fields of other types as well.
252 : * The value will be automatically converted for other field
253 : * types, with a possible loss of precision.
254 : *
255 : * This method is the same as the C function GDALRATSetValueAsString().
256 : *
257 : * @param iRow row to fetch (zero based).
258 : * @param iField column to fetch (zero based).
259 : * @param pszValue the value to assign.
260 : * @return (since 3.12) CE_None in case of success, error code otherwise
261 : */
262 : virtual CPLErr SetValue(int iRow, int iField, const char *pszValue) = 0;
263 :
264 : /**
265 : * \brief Set field value from integer.
266 : *
267 : * The indicated field (column) on the indicated row is set from the
268 : * passed value. This method is nominally called on fields of type
269 : * GFT_Integer, but it can be called on fields of other types as well.
270 : * The value will be automatically converted for other field
271 : * types, with a possible loss of precision.
272 : *
273 : * This method is the same as the C function GDALRATSetValueAsInteger().
274 : *
275 : * @param iRow row to fetch (zero based).
276 : * @param iField column to fetch (zero based).
277 : * @param nValue the value to assign.
278 : * @return (since 3.12) CE_None in case of success, error code otherwise
279 : */
280 : virtual CPLErr SetValue(int iRow, int iField, int nValue) = 0;
281 :
282 : /**
283 : * \brief Set field value from double.
284 : *
285 : * The indicated field (column) on the indicated row is set from the
286 : * passed value. This method is nominally called on fields of type
287 : * GFT_Real, but it can be called on fields of other types as well.
288 : * The value will be automatically converted for other field
289 : * types, with a possible loss of precision.
290 : *
291 : * This method is the same as the C function GDALRATSetValueAsDouble().
292 : *
293 : * @param iRow row to fetch (zero based).
294 : * @param iField column to fetch (zero based).
295 : * @param dfValue the value to assign.
296 : * @return (since 3.12) CE_None in case of success, error code otherwise
297 : */
298 : virtual CPLErr SetValue(int iRow, int iField, double dfValue) = 0;
299 :
300 : /**
301 : * \brief Set field value from boolean.
302 : *
303 : * The indicated field (column) on the indicated row is set from the
304 : * passed value. This method is nominally called on fields of type
305 : * GFT_Boolean, but it can be called on fields of other types as well.
306 : * The value will be automatically converted for other field
307 : * types, with a possible loss of precision.
308 : *
309 : * This method is the same as the C function GDALRATSetValueAsBoolean().
310 : *
311 : * @param iRow row to fetch (zero based).
312 : * @param iField column to fetch (zero based).
313 : * @param bValue the value to assign.
314 : * @return CE_None in case of success, error code otherwise
315 : * @since 3.12
316 : */
317 : virtual CPLErr SetValue(int iRow, int iField, bool bValue) = 0;
318 :
319 : /**
320 : * \brief Set field value from datetime.
321 : *
322 : * The indicated field (column) on the indicated row is set from the
323 : * passed value. Besides being called on a field of type GFT_DateTime, this
324 : * method can also be called on a field of type GFT_String, in which case
325 : * the datetime will be converted into its ISO-8601 representation.
326 : *
327 : * Note that the GDALRATDateTime::bIsValid field must be set to true if
328 : * the date time is valid.
329 : *
330 : * This method is the same as the C function GDALRATSetValueAsDateTime().
331 : *
332 : * @param iRow row to fetch (zero based).
333 : * @param iField column to fetch (zero based).
334 : * @param sDateTime Date time value
335 : * @return CE_None in case of success, error code otherwise
336 : * @since 3.12
337 : */
338 : virtual CPLErr SetValue(int iRow, int iField,
339 : const GDALRATDateTime &sDateTime) = 0;
340 :
341 : /**
342 : * \brief Set field value from a WKB geometry.
343 : *
344 : * The indicated field (column) on the indicated row is set from the
345 : * passed value. Besides being called on a field of type GFT_WKBGeometry, this
346 : * method can also be called on a field of type GFT_String, in which case
347 : * the datetime will be converted into its WKT geometry representation.
348 : *
349 : * This method is the same as the C function GDALRATSetValueAsWKBGeometry().
350 : *
351 : * @param iRow row to fetch (zero based).
352 : * @param iField column to fetch (zero based).
353 : * @param pabyWKB Pointer to a WKB encoded geometry
354 : * @param nWKBSize Number of bytes of pabyWKB.
355 : * @return CE_None in case of success, error code otherwise
356 : * @since 3.12
357 : */
358 : virtual CPLErr SetValue(int iRow, int iField, const void *pabyWKB,
359 : size_t nWKBSize) = 0;
360 :
361 : /**
362 : * \brief Determine whether changes made to this RAT are reflected directly
363 : * in the dataset
364 : *
365 : * If this returns FALSE then GDALRasterBand.SetDefaultRAT() should be
366 : * called. Otherwise this is unnecessary since changes to this object are
367 : * reflected in the dataset.
368 : *
369 : * This method is the same as the C function
370 : * GDALRATChangesAreWrittenToFile().
371 : *
372 : */
373 : virtual int ChangesAreWrittenToFile() = 0;
374 :
375 : /**
376 : * \brief Set the RAT table type.
377 : *
378 : * Set whether the RAT is thematic or athematic (continuous).
379 : *
380 : */
381 : virtual CPLErr SetTableType(const GDALRATTableType eInTableType) = 0;
382 :
383 : /**
384 : * \brief Get the RAT table type.
385 : *
386 : * Indicates whether the RAT is thematic or athematic (continuous).
387 : *
388 : * @return table type
389 : */
390 : virtual GDALRATTableType GetTableType() const = 0;
391 :
392 : virtual CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow,
393 : int iLength, double *pdfData);
394 : virtual CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow,
395 : int iLength, int *pnData);
396 : virtual CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow,
397 : int iLength, char **papszStrList);
398 : virtual CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow,
399 : int iLength, bool *pbData);
400 : virtual CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow,
401 : int iLength, GDALRATDateTime *pasDateTime);
402 : virtual CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow,
403 : int iLength, GByte **ppabyWKB, size_t *pnWKBSize);
404 :
405 : virtual void SetRowCount(int iCount);
406 : virtual int GetRowOfValue(double dfValue) const;
407 : virtual int GetRowOfValue(int nValue) const;
408 :
409 : virtual CPLErr CreateColumn(const char *pszFieldName,
410 : GDALRATFieldType eFieldType,
411 : GDALRATFieldUsage eFieldUsage);
412 : virtual CPLErr SetLinearBinning(double dfRow0Min, double dfBinSize);
413 : virtual int GetLinearBinning(double *pdfRow0Min, double *pdfBinSize) const;
414 :
415 : /**
416 : * \brief Serialize
417 : *
418 : * May fail (return nullptr) if the attribute table is too large to
419 : * serialize (GetRowCount() * GetColCount() > RAT_MAX_ELEM_FOR_CLONE)
420 : */
421 : virtual CPLXMLNode *Serialize() const;
422 : virtual void *SerializeJSON() const;
423 : virtual CPLErr XMLInit(const CPLXMLNode *, const char *);
424 :
425 : virtual CPLErr InitializeFromColorTable(const GDALColorTable *);
426 : virtual GDALColorTable *TranslateToColorTable(int nEntryCount = -1);
427 :
428 : virtual void DumpReadable(FILE * = nullptr);
429 :
430 : /** Convert a GDALRasterAttributeTable* to a GDALRasterAttributeTableH.
431 : */
432 : static inline GDALRasterAttributeTableH
433 1157 : ToHandle(GDALRasterAttributeTable *poRAT)
434 : {
435 1157 : return static_cast<GDALRasterAttributeTableH>(poRAT);
436 : }
437 :
438 : /** Convert a GDALRasterAttributeTableH to a GDALRasterAttributeTable*.
439 : */
440 : static inline GDALRasterAttributeTable *
441 1833 : FromHandle(GDALRasterAttributeTableH hRAT)
442 : {
443 1833 : return static_cast<GDALRasterAttributeTable *>(hRAT);
444 : }
445 :
446 : /**
447 : * \brief Remove statistics from the RAT.
448 : *
449 : */
450 : virtual void RemoveStatistics() = 0;
451 :
452 : //! @cond Doxygen_Suppress
453 : static std::string DateTimeToString(const GDALRATDateTime &sDateTime);
454 : static bool StringToDateTime(const char *pszStr,
455 : GDALRATDateTime &sDateTime);
456 :
457 : static std::string WKBGeometryToWKT(const void *pabyWKB, size_t nWKBSize);
458 : static std::vector<GByte> WKTGeometryToWKB(const char *pszWKT);
459 : //! @endcond
460 :
461 : protected:
462 : //! @cond Doxygen_Suppress
463 1210 : GDALRasterAttributeTable() = default;
464 28 : GDALRasterAttributeTable(const GDALRasterAttributeTable &) = default;
465 : GDALRasterAttributeTable &
466 : operator=(const GDALRasterAttributeTable &) = default;
467 : GDALRasterAttributeTable(GDALRasterAttributeTable &&) = default;
468 : GDALRasterAttributeTable &operator=(GDALRasterAttributeTable &&) = default;
469 :
470 : CPLErr ValuesIOBooleanFromIntoInt(GDALRWFlag eRWFlag, int iField,
471 : int iStartRow, int iLength, bool *pbData);
472 : CPLErr ValuesIODateTimeFromIntoString(GDALRWFlag eRWFlag, int iField,
473 : int iStartRow, int iLength,
474 : GDALRATDateTime *psDateTime);
475 : CPLErr ValuesIOWKBGeometryFromIntoString(GDALRWFlag eRWFlag, int iField,
476 : int iStartRow, int iLength,
477 : GByte **ppabyWKB,
478 : size_t *pnWKBSize);
479 : //! @endcond
480 : };
481 :
482 : /************************************************************************/
483 : /* GDALDefaultRasterAttributeTable */
484 : /************************************************************************/
485 :
486 : //! Raster Attribute Table container.
487 :
488 563 : class CPL_DLL GDALDefaultRasterAttributeTable : public GDALRasterAttributeTable
489 : {
490 : private:
491 : struct GDALRasterAttributeField
492 : {
493 : CPLString sName{};
494 :
495 : GDALRATFieldType eType = GFT_Integer;
496 :
497 : GDALRATFieldUsage eUsage = GFU_Generic;
498 :
499 : std::vector<GInt32> anValues{};
500 : std::vector<double> adfValues{};
501 : std::vector<CPLString> aosValues{};
502 : std::vector<bool> abValues{};
503 : std::vector<GDALRATDateTime> asDateTimeValues{};
504 : std::vector<std::vector<GByte>> aabyWKBGeometryValues{};
505 : };
506 :
507 : std::vector<GDALRasterAttributeField> aoFields{};
508 :
509 : int bLinearBinning = false; // TODO(schwehr): Can this be a bool?
510 : double dfRow0Min = -0.5;
511 : double dfBinSize = 1.0;
512 :
513 : GDALRATTableType eTableType = GRTT_THEMATIC;
514 :
515 : void AnalyseColumns();
516 : int bColumnsAnalysed = false; // TODO(schwehr): Can this be a bool?
517 : int nMinCol = -1;
518 : int nMaxCol = -1;
519 :
520 : int nRowCount = 0;
521 :
522 : CPLString osWorkingResult{};
523 : mutable std::vector<GByte> m_abyWKB{};
524 :
525 : public:
526 : GDALDefaultRasterAttributeTable();
527 : ~GDALDefaultRasterAttributeTable() override;
528 :
529 : //! @cond Doxygen_Suppress
530 28 : GDALDefaultRasterAttributeTable(const GDALDefaultRasterAttributeTable &) =
531 : default;
532 : GDALDefaultRasterAttributeTable &
533 : operator=(const GDALDefaultRasterAttributeTable &) = default;
534 : GDALDefaultRasterAttributeTable(GDALDefaultRasterAttributeTable &&) =
535 : default;
536 : GDALDefaultRasterAttributeTable &
537 : operator=(GDALDefaultRasterAttributeTable &&) = default;
538 : //! @endcond
539 :
540 : GDALDefaultRasterAttributeTable *Clone() const override;
541 :
542 : int GetColumnCount() const override;
543 :
544 : const char *GetNameOfCol(int) const override;
545 : GDALRATFieldUsage GetUsageOfCol(int) const override;
546 : GDALRATFieldType GetTypeOfCol(int) const override;
547 :
548 : int GetColOfUsage(GDALRATFieldUsage) const override;
549 :
550 : int GetRowCount() const override;
551 :
552 : const char *GetValueAsString(int iRow, int iField) const override;
553 : int GetValueAsInt(int iRow, int iField) const override;
554 : double GetValueAsDouble(int iRow, int iField) const override;
555 : bool GetValueAsBoolean(int iRow, int iField) const override;
556 : GDALRATDateTime GetValueAsDateTime(int iRow, int iField) const override;
557 : const GByte *GetValueAsWKBGeometry(int iRow, int iField,
558 : size_t &nWKBSize) const override;
559 :
560 : CPLErr SetValue(int iRow, int iField, const char *pszValue) override;
561 : CPLErr SetValue(int iRow, int iField, double dfValue) override;
562 : CPLErr SetValue(int iRow, int iField, int nValue) override;
563 : CPLErr SetValue(int iRow, int iField, bool bValue) override;
564 : CPLErr SetValue(int iRow, int iField,
565 : const GDALRATDateTime &sDateTime) override;
566 : CPLErr SetValue(int iRow, int iField, const void *pabyWKB,
567 : size_t nWKBSize) override;
568 :
569 : int ChangesAreWrittenToFile() override;
570 : void SetRowCount(int iCount) override;
571 :
572 : int GetRowOfValue(double dfValue) const override;
573 : int GetRowOfValue(int nValue) const override;
574 :
575 : CPLErr CreateColumn(const char *pszFieldName, GDALRATFieldType eFieldType,
576 : GDALRATFieldUsage eFieldUsage) override;
577 : CPLErr SetLinearBinning(double dfRow0Min, double dfBinSize) override;
578 : int GetLinearBinning(double *pdfRow0Min, double *pdfBinSize) const override;
579 :
580 : CPLErr SetTableType(const GDALRATTableType eInTableType) override;
581 : GDALRATTableType GetTableType() const override;
582 :
583 : void RemoveStatistics() override;
584 : };
585 :
586 : std::unique_ptr<GDALRasterAttributeTable>
587 : CPL_DLL GDALLoadVATDBF(const char *pszFilename);
588 :
589 : #endif /* ndef GDAL_RAT_H_INCLUDED */
|