1 /******************************************************************************
2  * $Id: gdal_rat.h 2519a7eb0e1649dbf8625ae8ffc7bb7c3ef9514b 2018-07-10 12:05:23 +0100 Robert Coup $
3  *
4  * Project:  GDAL Core
5  * Purpose:  GDALRasterAttributeTable class declarations.
6  * Author:   Frank Warmerdam, warmerdam@pobox.com
7  *
8  ******************************************************************************
9  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  ****************************************************************************/
29 
30 #ifndef GDAL_RAT_H_INCLUDED
31 #define GDAL_RAT_H_INCLUDED
32 
33 #include "cpl_minixml.h"
34 #include "gdal_priv.h"
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 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.  If the field is numeric, it is formatted as a string
135      * using default rules, so some precision may be lost.
136      *
137      * The returned string is temporary and cannot be expected to be
138      * available after the next GDAL call.
139      *
140      * This method is the same as the C function GDALRATGetValueAsString().
141      *
142      * @param iRow row to fetch (zero based).
143      * @param iField column to fetch (zero based).
144      *
145      * @return field value.
146      */
147     virtual const char   *GetValueAsString( int iRow, int iField ) const = 0;
148 
149     /**
150      * \brief Fetch field value as a integer.
151      *
152      * The value of the requested column in the requested row is returned
153      * as an integer.  Non-integer fields will be converted to integer with
154      * the possibility of data loss.
155      *
156      * This method is the same as the C function GDALRATGetValueAsInt().
157      *
158      * @param iRow row to fetch (zero based).
159      * @param iField column to fetch (zero based).
160      *
161      * @return field value
162      */
163     virtual int           GetValueAsInt( int iRow, int iField ) const = 0;
164 
165     /**
166      * \brief Fetch field value as a double.
167      *
168      * The value of the requested column in the requested row is returned
169      * as a double.   Non double fields will be converted to double with
170      * the possibility of data loss.
171      *
172      * This method is the same as the C function GDALRATGetValueAsDouble().
173      *
174      * @param iRow row to fetch (zero based).
175      * @param iField column to fetch (zero based).
176      *
177      * @return field value
178      */
179     virtual double        GetValueAsDouble( int iRow, int iField ) const = 0;
180 
181     /**
182      * \brief Set field value from string.
183      *
184      * The indicated field (column) on the indicated row is set from the
185      * passed value.  The value will be automatically converted for other field
186      * types, with a possible loss of precision.
187      *
188      * This method is the same as the C function GDALRATSetValueAsString().
189      *
190      * @param iRow row to fetch (zero based).
191      * @param iField column to fetch (zero based).
192      * @param pszValue the value to assign.
193      */
194     virtual void          SetValue( int iRow, int iField,
195                                     const char *pszValue ) = 0;
196 
197     /**
198      * \brief Set field value from integer.
199      *
200      * The indicated field (column) on the indicated row is set from the
201      * passed value.  The value will be automatically converted for other field
202      * types, with a possible loss of precision.
203      *
204      * This method is the same as the C function GDALRATSetValueAsInteger().
205      *
206      * @param iRow row to fetch (zero based).
207      * @param iField column to fetch (zero based).
208      * @param nValue the value to assign.
209      */
210     virtual void          SetValue( int iRow, int iField, int nValue ) = 0;
211 
212     /**
213      * \brief Set field value from double.
214      *
215      * The indicated field (column) on the indicated row is set from the
216      * passed value.  The value will be automatically converted for other field
217      * types, with a possible loss of precision.
218      *
219      * This method is the same as the C function GDALRATSetValueAsDouble().
220      *
221      * @param iRow row to fetch (zero based).
222      * @param iField column to fetch (zero based).
223      * @param dfValue the value to assign.
224      */
225     virtual void          SetValue( int iRow, int iField, double dfValue) = 0;
226 
227     /**
228      * \brief Determine whether changes made to this RAT are reflected directly
229      * in the dataset
230      *
231      * If this returns FALSE then GDALRasterBand.SetDefaultRAT() should be
232      * called. Otherwise this is unnecessary since changes to this object are
233      * reflected in the dataset.
234      *
235      * This method is the same as the C function
236      * GDALRATChangesAreWrittenToFile().
237      *
238      */
239     virtual int           ChangesAreWrittenToFile() = 0;
240 
241     /**
242      * \brief Set the RAT table type.
243      *
244      * Set whether the RAT is thematic or athematic (continuous).
245      *
246      * @since GDAL 2.4
247      */
248     virtual CPLErr        SetTableType(const GDALRATTableType eInTableType) = 0;
249 
250     /**
251      * \brief Get the RAT table type.
252      *
253      * Indicates whether the RAT is thematic or athematic (continuous).
254      *
255      * @since GDAL 2.4
256      * @return table type
257      */
258     virtual GDALRATTableType GetTableType() const = 0;
259 
260     virtual CPLErr        ValuesIO( GDALRWFlag eRWFlag, int iField,
261                                     int iStartRow, int iLength,
262                                     double *pdfData);
263     virtual CPLErr        ValuesIO( GDALRWFlag eRWFlag, int iField,
264                                     int iStartRow, int iLength, int *pnData);
265     virtual CPLErr        ValuesIO( GDALRWFlag eRWFlag, int iField,
266                                     int iStartRow, int iLength,
267                                     char **papszStrList);
268 
269     virtual void          SetRowCount( int iCount );
270     virtual int           GetRowOfValue( double dfValue ) const;
271     virtual int           GetRowOfValue( int nValue ) const;
272 
273     virtual CPLErr        CreateColumn( const char *pszFieldName,
274                                         GDALRATFieldType eFieldType,
275                                         GDALRATFieldUsage eFieldUsage );
276     virtual CPLErr        SetLinearBinning( double dfRow0Min,
277                                             double dfBinSize );
278     virtual int           GetLinearBinning( double *pdfRow0Min,
279                                             double *pdfBinSize ) const;
280 
281     /**
282      * \brief Serialize
283      *
284      * May fail (return nullptr) if the attribute table is too large to serialize
285      * (GetRowCount() * GetColCount() > RAT_MAX_ELEM_FOR_CLONE)
286      */
287     virtual CPLXMLNode   *Serialize() const;
288     virtual void   *SerializeJSON() const;
289     virtual CPLErr        XMLInit( CPLXMLNode *, const char * );
290 
291     virtual CPLErr        InitializeFromColorTable( const GDALColorTable * );
292     virtual GDALColorTable *TranslateToColorTable( int nEntryCount = -1 );
293 
294     virtual void          DumpReadable( FILE * = nullptr );
295 
296     /** Convert a GDALRasterAttributeTable* to a GDALRasterAttributeTableH.
297      * @since GDAL 2.3
298      */
ToHandle(GDALRasterAttributeTable * poRAT)299     static inline GDALRasterAttributeTableH ToHandle(GDALRasterAttributeTable* poRAT)
300         { return static_cast<GDALRasterAttributeTableH>(poRAT); }
301 
302     /** Convert a GDALRasterAttributeTableH to a GDALRasterAttributeTable*.
303      * @since GDAL 2.3
304      */
FromHandle(GDALRasterAttributeTableH hRAT)305     static inline GDALRasterAttributeTable* FromHandle(GDALRasterAttributeTableH hRAT)
306         { return static_cast<GDALRasterAttributeTable*>(hRAT); }
307 
308     /**
309      * \brief Remove statistics from the RAT.
310      *
311      * @since GDAL 2.4
312      */
313     virtual void          RemoveStatistics() = 0;
314 };
315 
316 /************************************************************************/
317 /*                       GDALRasterAttributeField                       */
318 /*                                                                      */
319 /*      (private)                                                       */
320 /************************************************************************/
321 //! @cond Doxygen_Suppress
322 class GDALRasterAttributeField
323 {
324  public:
325     CPLString         sName{};
326 
327     GDALRATFieldType  eType = GFT_Integer;
328 
329     GDALRATFieldUsage eUsage = GFU_Generic;
330 
331     std::vector<GInt32> anValues{};
332     std::vector<double> adfValues{};
333     std::vector<CPLString> aosValues{};
334 };
335 //! @endcond
336 
337 /************************************************************************/
338 /*                    GDALDefaultRasterAttributeTable                   */
339 /************************************************************************/
340 
341 //! Raster Attribute Table container.
342 
343 class CPL_DLL GDALDefaultRasterAttributeTable : public GDALRasterAttributeTable
344 {
345  private:
346     std::vector<GDALRasterAttributeField> aoFields{};
347 
348     int bLinearBinning = false;  // TODO(schwehr): Can this be a bool?
349     double dfRow0Min = -0.5;
350     double dfBinSize = 1.0;
351 
352     GDALRATTableType eTableType;
353 
354     void  AnalyseColumns();
355     int   bColumnsAnalysed = false;  // TODO(schwehr): Can this be a bool?
356     int   nMinCol = -1;
357     int   nMaxCol = -1;
358 
359     int   nRowCount = 0;
360 
361     CPLString osWorkingResult{};
362 
363  public:
364     GDALDefaultRasterAttributeTable();
365     ~GDALDefaultRasterAttributeTable() override;
366 
367     GDALDefaultRasterAttributeTable *Clone() const override;
368 
369     int GetColumnCount() const override;
370 
371     const char *GetNameOfCol( int ) const override;
372     GDALRATFieldUsage GetUsageOfCol( int ) const override;
373     GDALRATFieldType GetTypeOfCol( int ) const override;
374 
375     int GetColOfUsage( GDALRATFieldUsage ) const override;
376 
377     int GetRowCount() const override;
378 
379     const char *GetValueAsString( int iRow, int iField ) const override;
380     int GetValueAsInt( int iRow, int iField ) const override;
381     double GetValueAsDouble( int iRow, int iField ) const override;
382 
383     void SetValue( int iRow, int iField,
384                    const char *pszValue ) override;
385     void SetValue( int iRow, int iField, double dfValue) override;
386     void SetValue( int iRow, int iField, int nValue ) override;
387 
388     int ChangesAreWrittenToFile() override;
389     void SetRowCount( int iCount ) override;
390 
391     int GetRowOfValue( double dfValue ) const override;
392     int GetRowOfValue( int nValue ) const override;
393 
394     CPLErr CreateColumn( const char *pszFieldName,
395                          GDALRATFieldType eFieldType,
396                          GDALRATFieldUsage eFieldUsage ) override;
397     CPLErr SetLinearBinning( double dfRow0Min,
398                              double dfBinSize ) override;
399     int GetLinearBinning( double *pdfRow0Min,
400                           double *pdfBinSize ) const override;
401 
402     CPLErr        SetTableType(const GDALRATTableType eInTableType) override;
403     GDALRATTableType GetTableType() const override;
404 
405     void          RemoveStatistics() override;
406 };
407 
408 #endif /* ndef GDAL_RAT_H_INCLUDED */
409