mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-01 14:22:41 -06:00
1933 lines
64 KiB
C++
1933 lines
64 KiB
C++
/******************************************************************************
|
|
* $Id: gdal_rat.cpp 29243 2015-05-24 15:53:26Z rouault $
|
|
*
|
|
* Project: GDAL Core
|
|
* Purpose: Implementation of GDALRasterAttributeTable and related classes.
|
|
* Author: Frank Warmerdam, warmerdam@pobox.com
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2005, Frank Warmerdam
|
|
* Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "gdal_priv.h"
|
|
#include "gdal_rat.h"
|
|
#include "json.h"
|
|
#include "ogrgeojsonwriter.h"
|
|
|
|
CPL_CVSID("$Id: gdal_rat.cpp 29243 2015-05-24 15:53:26Z rouault $");
|
|
|
|
/**
|
|
* \class GDALRasterAttributeTable
|
|
*
|
|
* The GDALRasterAttributeTable (or RAT) class is used to encapsulate a table
|
|
* used to provide attribute information about pixel values. Each row
|
|
* in the table applies to a range of pixel values (or a single value in
|
|
* some cases), and might have attributes such as the histogram count for
|
|
* that range, the color pixels of that range should be drawn names of classes
|
|
* or any other generic information.
|
|
*
|
|
* Raster attribute tables can be used to represent histograms, color tables,
|
|
* and classification information.
|
|
*
|
|
* Each column in a raster attribute table has a name, a type (integer,
|
|
* floating point or string), and a GDALRATFieldUsage. The usage distinguishes
|
|
* columns with particular understood purposes (such as color, histogram
|
|
* count, name) and columns that have specific purposes not understood by
|
|
* the library (long label, suitability_for_growing_wheat, etc).
|
|
*
|
|
* In the general case each row has a column indicating the minimum pixel
|
|
* values falling into that category, and a column indicating the maximum
|
|
* pixel value. These are indicated with usage values of GFU_Min, and
|
|
* GFU_Max. In other cases where each row is a discrete pixel value, one
|
|
* column of usage GFU_MinMax can be used.
|
|
*
|
|
* In other cases all the categories are of equal size and regularly spaced
|
|
* and the categorization information can be determine just by knowing the
|
|
* value at which the categories start, and the size of a category. This
|
|
* is called "Linear Binning" and the information is kept specially on
|
|
* the raster attribute table as a whole.
|
|
*
|
|
* RATs are normally associated with GDALRasterBands and be be queried
|
|
* using the GDALRasterBand::GetDefaultRAT() method.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* ~GDALRasterAttributeTable() */
|
|
/* */
|
|
/* Virtual Destructor */
|
|
/************************************************************************/
|
|
|
|
GDALRasterAttributeTable::~GDALRasterAttributeTable()
|
|
{
|
|
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ValuesIO() */
|
|
/* */
|
|
/* Default Implementations */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Read or Write a block of doubles to/from the Attribute Table.
|
|
*
|
|
* This method is the same as the C function GDALRATValuesIOAsDouble().
|
|
*
|
|
* @param eRWFlag Either GF_Read or GF_Write
|
|
* @param iField column of the Attribute Table
|
|
* @param iStartRow start row to start reading/writing (zero based)
|
|
* @param iLength number of rows to read or write
|
|
* @param pdfData pointer to array of doubles to read/write. Should be at least iLength long.
|
|
*
|
|
* @return CE_None or CE_Failure if iStartRow + iLength greater than number of rows in table.
|
|
*/
|
|
|
|
CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData)
|
|
{
|
|
int iIndex;
|
|
|
|
if( (iStartRow + iLength) > GetRowCount() )
|
|
{
|
|
return CE_Failure;
|
|
}
|
|
|
|
if( eRWFlag == GF_Read )
|
|
{
|
|
for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
|
|
{
|
|
pdfData[iIndex] = GetValueAsDouble(iIndex, iField);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
|
|
{
|
|
SetValue(iIndex, iField, pdfData[iIndex]);
|
|
}
|
|
}
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATValuesIOAsDouble() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Read or Write a block of doubles to/from the Attribute Table.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::ValuesIO()
|
|
*/
|
|
CPLErr CPL_STDCALL GDALRATValuesIOAsDouble( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag,
|
|
int iField, int iStartRow, int iLength, double *pdfData )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATValuesIOAsDouble", CE_Failure );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->ValuesIO(eRWFlag, iField, iStartRow, iLength, pdfData);
|
|
}
|
|
|
|
/**
|
|
* \brief Read or Write a block of integers to/from the Attribute Table.
|
|
*
|
|
* This method is the same as the C function GDALRATValuesIOAsInteger().
|
|
*
|
|
* @param eRWFlag Either GF_Read or GF_Write
|
|
* @param iField column of the Attribute Table
|
|
* @param iStartRow start row to start reading/writing (zero based)
|
|
* @param iLength number of rows to read or write
|
|
* @param pnData pointer to array of ints to read/write. Should be at least iLength long.
|
|
*
|
|
* @return CE_None or CE_Failure if iStartRow + iLength greater than number of rows in table.
|
|
*/
|
|
|
|
CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData)
|
|
{
|
|
int iIndex;
|
|
|
|
if( (iStartRow + iLength) > GetRowCount() )
|
|
{
|
|
return CE_Failure;
|
|
}
|
|
|
|
if( eRWFlag == GF_Read )
|
|
{
|
|
for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
|
|
{
|
|
pnData[iIndex] = GetValueAsInt(iIndex, iField);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
|
|
{
|
|
SetValue(iIndex, iField, pnData[iIndex]);
|
|
}
|
|
}
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATValuesIOAsInteger() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Read or Write a block of ints to/from the Attribute Table.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::ValuesIO()
|
|
*/
|
|
CPLErr CPL_STDCALL GDALRATValuesIOAsInteger( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag,
|
|
int iField, int iStartRow, int iLength, int *pnData)
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATValuesIOAsInteger", CE_Failure );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->ValuesIO(eRWFlag, iField, iStartRow, iLength, pnData);
|
|
}
|
|
|
|
/**
|
|
* \brief Read or Write a block of strings to/from the Attribute Table.
|
|
*
|
|
* This method is the same as the C function GDALRATValuesIOAsString().
|
|
* When reading, papszStrList must be already allocated to the correct size.
|
|
* The caller is expected to call CPLFree on each read string.
|
|
*
|
|
* @param eRWFlag Either GF_Read or GF_Write
|
|
* @param iField column of the Attribute Table
|
|
* @param iStartRow start row to start reading/writing (zero based)
|
|
* @param iLength number of rows to read or write
|
|
* @param papszStrList pointer to array of strings to read/write. Should be at least iLength long.
|
|
*
|
|
* @return CE_None or CE_Failure if iStartRow + iLength greater than number of rows in table.
|
|
*/
|
|
|
|
CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList)
|
|
{
|
|
int iIndex;
|
|
|
|
if( (iStartRow + iLength) > GetRowCount() )
|
|
{
|
|
return CE_Failure;
|
|
}
|
|
|
|
if( eRWFlag == GF_Read )
|
|
{
|
|
for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
|
|
{
|
|
papszStrList[iIndex] = VSIStrdup(GetValueAsString(iIndex, iField));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++ )
|
|
{
|
|
SetValue(iIndex, iField, papszStrList[iIndex]);
|
|
}
|
|
}
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATValuesIOAsString() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Read or Write a block of strings to/from the Attribute Table.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::ValuesIO()
|
|
*/
|
|
CPLErr CPL_STDCALL GDALRATValuesIOAsString( GDALRasterAttributeTableH hRAT, GDALRWFlag eRWFlag,
|
|
int iField, int iStartRow, int iLength, char **papszStrList)
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATValuesIOAsString", CE_Failure );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->ValuesIO(eRWFlag, iField, iStartRow, iLength, papszStrList);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetRowCount() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Set row count.
|
|
*
|
|
* Resizes the table to include the indicated number of rows. Newly created
|
|
* rows will be initialized to their default values - "" for strings,
|
|
* and zero for numeric fields.
|
|
*
|
|
* This method is the same as the C function GDALRATSetRowCount().
|
|
*
|
|
* @param nNewCount the new number of rows.
|
|
*/
|
|
|
|
void GDALRasterAttributeTable::SetRowCount( CPL_UNUSED int nNewCount )
|
|
{
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATSetRowCount() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Set row count.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::SetRowCount()
|
|
*/
|
|
void CPL_STDCALL
|
|
GDALRATSetRowCount( GDALRasterAttributeTableH hRAT, int nNewCount )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hRAT, "GDALRATSetRowCount" );
|
|
|
|
((GDALRasterAttributeTable *) hRAT)->SetRowCount( nNewCount );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetRowOfValue() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Get row for pixel value.
|
|
*
|
|
* Given a raw pixel value, the raster attribute table is scanned to
|
|
* determine which row in the table applies to the pixel value. The
|
|
* row index is returned.
|
|
*
|
|
* This method is the same as the C function GDALRATGetRowOfValue().
|
|
*
|
|
* @param dfValue the pixel value.
|
|
*
|
|
* @return the row index or -1 if no row is appropriate.
|
|
*/
|
|
|
|
int GDALRasterAttributeTable::GetRowOfValue( CPL_UNUSED double dfValue ) const
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetRowOfValue() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Get row for pixel value.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetRowOfValue()
|
|
*/
|
|
int CPL_STDCALL
|
|
GDALRATGetRowOfValue( GDALRasterAttributeTableH hRAT, double dfValue )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetRowOfValue", 0 );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetRowOfValue( dfValue );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetRowOfValue() */
|
|
/* */
|
|
/* Int arg for now just converted to double. Perhaps we will */
|
|
/* handle this in a special way some day? */
|
|
/************************************************************************/
|
|
|
|
int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
|
|
|
|
{
|
|
return GetRowOfValue( (double) nValue );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CreateColumn() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Create new column.
|
|
*
|
|
* If the table already has rows, all row values for the new column will
|
|
* be initialized to the default value ("", or zero). The new column is
|
|
* always created as the last column, can will be column (field)
|
|
* "GetColumnCount()-1" after CreateColumn() has completed successfully.
|
|
*
|
|
* This method is the same as the C function GDALRATCreateColumn().
|
|
*
|
|
* @param pszFieldName the name of the field to create.
|
|
* @param eFieldType the field type (integer, double or string).
|
|
* @param eFieldUsage the field usage, GFU_Generic if not known.
|
|
*
|
|
* @return CE_None on success or CE_Failure if something goes wrong.
|
|
*/
|
|
|
|
CPLErr GDALRasterAttributeTable::CreateColumn( CPL_UNUSED const char *pszFieldName,
|
|
CPL_UNUSED GDALRATFieldType eFieldType,
|
|
CPL_UNUSED GDALRATFieldUsage eFieldUsage )
|
|
{
|
|
return CE_Failure;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATCreateColumn() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Create new column.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::CreateColumn()
|
|
*/
|
|
CPLErr CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH hRAT,
|
|
const char *pszFieldName,
|
|
GDALRATFieldType eFieldType,
|
|
GDALRATFieldUsage eFieldUsage )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATCreateColumn", CE_Failure );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->CreateColumn( pszFieldName,
|
|
eFieldType,
|
|
eFieldUsage );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetLinearBinning() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Set linear binning information.
|
|
*
|
|
* For RATs with equal sized categories (in pixel value space) that are
|
|
* evenly spaced, this method may be used to associate the linear binning
|
|
* information with the table.
|
|
*
|
|
* This method is the same as the C function GDALRATSetLinearBinning().
|
|
*
|
|
* @param dfRow0MinIn the lower bound (pixel value) of the first category.
|
|
* @param dfBinSizeIn the width of each category (in pixel value units).
|
|
*
|
|
* @return CE_None on success or CE_Failure on failure.
|
|
*/
|
|
|
|
CPLErr GDALRasterAttributeTable::SetLinearBinning( CPL_UNUSED double dfRow0MinIn,
|
|
CPL_UNUSED double dfBinSizeIn )
|
|
{
|
|
return CE_Failure;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATSetLinearBinning() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Set linear binning information.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::SetLinearBinning()
|
|
*/
|
|
CPLErr CPL_STDCALL
|
|
GDALRATSetLinearBinning( GDALRasterAttributeTableH hRAT,
|
|
double dfRow0Min, double dfBinSize )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATSetLinearBinning", CE_Failure );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->SetLinearBinning(
|
|
dfRow0Min, dfBinSize );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetLinearBinning() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Get linear binning information.
|
|
*
|
|
* Returns linear binning information if any is associated with the RAT.
|
|
*
|
|
* This method is the same as the C function GDALRATGetLinearBinning().
|
|
*
|
|
* @param pdfRow0Min (out) the lower bound (pixel value) of the first category.
|
|
* @param pdfBinSize (out) the width of each category (in pixel value units).
|
|
*
|
|
* @return TRUE if linear binning information exists or FALSE if there is none.
|
|
*/
|
|
|
|
int GDALRasterAttributeTable::GetLinearBinning( CPL_UNUSED double *pdfRow0Min,
|
|
CPL_UNUSED double *pdfBinSize ) const
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetLinearBinning() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Get linear binning information.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetLinearBinning()
|
|
*/
|
|
int CPL_STDCALL
|
|
GDALRATGetLinearBinning( GDALRasterAttributeTableH hRAT,
|
|
double *pdfRow0Min, double *pdfBinSize )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetLinearBinning", 0 );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetLinearBinning(
|
|
pdfRow0Min, pdfBinSize );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Serialize() */
|
|
/************************************************************************/
|
|
|
|
CPLXMLNode *GDALRasterAttributeTable::Serialize() const
|
|
|
|
{
|
|
CPLXMLNode *psTree = NULL;
|
|
CPLXMLNode *psRow = NULL;
|
|
|
|
if( ( GetColumnCount() == 0 ) && ( GetRowCount() == 0 ) )
|
|
return NULL;
|
|
|
|
psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALRasterAttributeTable" );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Add attributes with regular binning info if appropriate. */
|
|
/* -------------------------------------------------------------------- */
|
|
char szValue[128];
|
|
double dfRow0Min, dfBinSize;
|
|
|
|
if( GetLinearBinning(&dfRow0Min, &dfBinSize) )
|
|
{
|
|
CPLsprintf( szValue, "%.16g", dfRow0Min );
|
|
CPLCreateXMLNode(
|
|
CPLCreateXMLNode( psTree, CXT_Attribute, "Row0Min" ),
|
|
CXT_Text, szValue );
|
|
|
|
CPLsprintf( szValue, "%.16g", dfBinSize );
|
|
CPLCreateXMLNode(
|
|
CPLCreateXMLNode( psTree, CXT_Attribute, "BinSize" ),
|
|
CXT_Text, szValue );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Define each column. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iCol;
|
|
int iColCount = GetColumnCount();
|
|
|
|
for( iCol = 0; iCol < iColCount; iCol++ )
|
|
{
|
|
CPLXMLNode *psCol;
|
|
|
|
psCol = CPLCreateXMLNode( psTree, CXT_Element, "FieldDefn" );
|
|
|
|
sprintf( szValue, "%d", iCol );
|
|
CPLCreateXMLNode(
|
|
CPLCreateXMLNode( psCol, CXT_Attribute, "index" ),
|
|
CXT_Text, szValue );
|
|
|
|
CPLCreateXMLElementAndValue( psCol, "Name",
|
|
GetNameOfCol(iCol) );
|
|
|
|
sprintf( szValue, "%d", (int) GetTypeOfCol(iCol) );
|
|
CPLCreateXMLElementAndValue( psCol, "Type", szValue );
|
|
|
|
sprintf( szValue, "%d", (int) GetUsageOfCol(iCol) );
|
|
CPLCreateXMLElementAndValue( psCol, "Usage", szValue );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Write out each row. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iRow;
|
|
int iRowCount = GetRowCount();
|
|
CPLXMLNode *psTail = NULL;
|
|
|
|
for( iRow = 0; iRow < iRowCount; iRow++ )
|
|
{
|
|
psRow = CPLCreateXMLNode( NULL, CXT_Element, "Row" );
|
|
if( psTail == NULL )
|
|
CPLAddXMLChild( psTree, psRow );
|
|
else
|
|
psTail->psNext = psRow;
|
|
psTail = psRow;
|
|
|
|
sprintf( szValue, "%d", iRow );
|
|
CPLCreateXMLNode(
|
|
CPLCreateXMLNode( psRow, CXT_Attribute, "index" ),
|
|
CXT_Text, szValue );
|
|
|
|
for( iCol = 0; iCol < iColCount; iCol++ )
|
|
{
|
|
const char *pszValue = szValue;
|
|
|
|
if( GetTypeOfCol(iCol) == GFT_Integer )
|
|
sprintf( szValue, "%d", GetValueAsInt(iRow, iCol) );
|
|
else if( GetTypeOfCol(iCol) == GFT_Real )
|
|
CPLsprintf( szValue, "%.16g", GetValueAsDouble(iRow, iCol) );
|
|
else
|
|
pszValue = GetValueAsString(iRow, iCol);
|
|
|
|
CPLCreateXMLElementAndValue( psRow, "F", pszValue );
|
|
}
|
|
}
|
|
|
|
return psTree;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SerializeJSON() */
|
|
/************************************************************************/
|
|
|
|
void *GDALRasterAttributeTable::SerializeJSON() const
|
|
|
|
{
|
|
json_object *poRAT = json_object_new_object();
|
|
|
|
if( ( GetColumnCount() == 0 ) && ( GetRowCount() == 0 ) )
|
|
return poRAT;
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Add attributes with regular binning info if appropriate. */
|
|
/* -------------------------------------------------------------------- */
|
|
double dfRow0Min, dfBinSize;
|
|
json_object *poRow0Min, *poBinSize;
|
|
|
|
if( GetLinearBinning(&dfRow0Min, &dfBinSize) )
|
|
{
|
|
poRow0Min = json_object_new_double_with_precision( dfRow0Min, 16 );
|
|
json_object_object_add( poRAT, "row0Min", poRow0Min );
|
|
|
|
poBinSize = json_object_new_double_with_precision( dfBinSize, 16 );
|
|
json_object_object_add( poRAT, "binSize", poBinSize );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Define each column. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iCol;
|
|
int iColCount = GetColumnCount();
|
|
json_object *poFieldDefnArray = json_object_new_array();
|
|
json_object *poFieldDefn, *poColumnIndex, *poName, *poType, *poUsage;
|
|
|
|
for( iCol = 0; iCol < iColCount; iCol++ )
|
|
{
|
|
poFieldDefn = json_object_new_object();
|
|
|
|
poColumnIndex = json_object_new_int( iCol );
|
|
json_object_object_add( poFieldDefn, "index", poColumnIndex );
|
|
|
|
poName = json_object_new_string( GetNameOfCol(iCol) );
|
|
json_object_object_add( poFieldDefn, "name", poName );
|
|
|
|
poType = json_object_new_int( (int) GetTypeOfCol(iCol) );
|
|
json_object_object_add( poFieldDefn, "type", poType );
|
|
|
|
poUsage = json_object_new_int( (int) GetUsageOfCol(iCol) );
|
|
json_object_object_add( poFieldDefn, "usage", poUsage );
|
|
|
|
json_object_array_add( poFieldDefnArray, poFieldDefn );
|
|
}
|
|
|
|
json_object_object_add( poRAT, "fieldDefn", poFieldDefnArray );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Write out each row. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iRow;
|
|
int iRowCount = GetRowCount();
|
|
json_object *poRowArray = json_object_new_array();
|
|
json_object *poRow, *poRowIndex, *poFArray, *poF;
|
|
|
|
for( iRow = 0; iRow < iRowCount; iRow++ )
|
|
{
|
|
poRow = json_object_new_object();
|
|
|
|
poRowIndex = json_object_new_int(iRow);
|
|
json_object_object_add( poRow, "index", poRowIndex );
|
|
|
|
poFArray = json_object_new_array();
|
|
|
|
for( iCol = 0; iCol < iColCount; iCol++ )
|
|
{
|
|
if( GetTypeOfCol(iCol) == GFT_Integer )
|
|
poF = json_object_new_int( GetValueAsInt(iRow, iCol) );
|
|
else if( GetTypeOfCol(iCol) == GFT_Real )
|
|
poF = json_object_new_double_with_precision( GetValueAsDouble(iRow, iCol), 16 );
|
|
else
|
|
poF = json_object_new_string( GetValueAsString(iRow, iCol) );
|
|
|
|
json_object_array_add( poFArray, poF );
|
|
}
|
|
json_object_object_add( poRow, "f", poFArray );
|
|
json_object_array_add( poRowArray, poRow );
|
|
}
|
|
json_object_object_add( poRAT, "row", poRowArray );
|
|
|
|
return poRAT;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* XMLInit() */
|
|
/************************************************************************/
|
|
|
|
CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree,
|
|
const char * /*pszVRTPath*/ )
|
|
|
|
{
|
|
CPLAssert( GetRowCount() == 0 && GetColumnCount() == 0 );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Linear binning. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( CPLGetXMLValue( psTree, "Row0Min", NULL )
|
|
&& CPLGetXMLValue( psTree, "BinSize", NULL ) )
|
|
{
|
|
SetLinearBinning( CPLAtof(CPLGetXMLValue( psTree, "Row0Min","" )),
|
|
CPLAtof(CPLGetXMLValue( psTree, "BinSize","" )) );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Column definitions */
|
|
/* -------------------------------------------------------------------- */
|
|
CPLXMLNode *psChild;
|
|
|
|
for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
|
|
{
|
|
if( psChild->eType == CXT_Element
|
|
&& EQUAL(psChild->pszValue,"FieldDefn") )
|
|
{
|
|
CreateColumn(
|
|
CPLGetXMLValue( psChild, "Name", "" ),
|
|
(GDALRATFieldType) atoi(CPLGetXMLValue( psChild, "Type", "1" )),
|
|
(GDALRATFieldUsage) atoi(CPLGetXMLValue( psChild, "Usage","0")));
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Row data. */
|
|
/* -------------------------------------------------------------------- */
|
|
for( psChild = psTree->psChild; psChild != NULL; psChild = psChild->psNext)
|
|
{
|
|
if( psChild->eType == CXT_Element
|
|
&& EQUAL(psChild->pszValue,"Row") )
|
|
{
|
|
int iRow = atoi(CPLGetXMLValue(psChild,"index","0"));
|
|
int iField = 0;
|
|
CPLXMLNode *psF;
|
|
|
|
for( psF = psChild->psChild; psF != NULL; psF = psF->psNext )
|
|
{
|
|
if( psF->eType != CXT_Element || !EQUAL(psF->pszValue,"F") )
|
|
continue;
|
|
|
|
if( psF->psChild != NULL && psF->psChild->eType == CXT_Text )
|
|
SetValue( iRow, iField++, psF->psChild->pszValue );
|
|
else
|
|
SetValue( iRow, iField++, "" );
|
|
}
|
|
}
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* InitializeFromColorTable() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Initialize from color table.
|
|
*
|
|
* This method will setup a whole raster attribute table based on the
|
|
* contents of the passed color table. The Value (GFU_MinMax),
|
|
* Red (GFU_Red), Green (GFU_Green), Blue (GFU_Blue), and Alpha (GFU_Alpha)
|
|
* fields are created, and a row is set for each entry in the color table.
|
|
*
|
|
* The raster attribute table must be empty before calling
|
|
* InitializeFromColorTable().
|
|
*
|
|
* The Value fields are set based on the implicit assumption with color
|
|
* tables that entry 0 applies to pixel value 0, 1 to 1, etc.
|
|
*
|
|
* This method is the same as the C function GDALRATInitializeFromColorTable().
|
|
*
|
|
* @param poTable the color table to copy from.
|
|
*
|
|
* @return CE_None on success or CE_Failure if something goes wrong.
|
|
*/
|
|
|
|
CPLErr GDALRasterAttributeTable::InitializeFromColorTable(
|
|
const GDALColorTable *poTable )
|
|
|
|
{
|
|
int iRow;
|
|
|
|
if( GetRowCount() > 0 || GetColumnCount() > 0 )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"Raster Attribute Table not empty in InitializeFromColorTable()" );
|
|
return CE_Failure;
|
|
}
|
|
|
|
SetLinearBinning( 0.0, 1.0 );
|
|
CreateColumn( "Value", GFT_Integer, GFU_MinMax );
|
|
CreateColumn( "Red", GFT_Integer, GFU_Red );
|
|
CreateColumn( "Green", GFT_Integer, GFU_Green );
|
|
CreateColumn( "Blue", GFT_Integer, GFU_Blue );
|
|
CreateColumn( "Alpha", GFT_Integer, GFU_Alpha );
|
|
|
|
SetRowCount( poTable->GetColorEntryCount() );
|
|
|
|
for( iRow = 0; iRow < poTable->GetColorEntryCount(); iRow++ )
|
|
{
|
|
GDALColorEntry sEntry;
|
|
|
|
poTable->GetColorEntryAsRGB( iRow, &sEntry );
|
|
|
|
SetValue( iRow, 0, iRow );
|
|
SetValue( iRow, 1, sEntry.c1 );
|
|
SetValue( iRow, 2, sEntry.c2 );
|
|
SetValue( iRow, 3, sEntry.c3 );
|
|
SetValue( iRow, 4, sEntry.c4 );
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATInitializeFromColorTable() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Initialize from color table.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::InitializeFromColorTable()
|
|
*/
|
|
CPLErr CPL_STDCALL
|
|
GDALRATInitializeFromColorTable( GDALRasterAttributeTableH hRAT,
|
|
GDALColorTableH hCT )
|
|
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATInitializeFromColorTable", CE_Failure );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->
|
|
InitializeFromColorTable( (GDALColorTable *) hCT );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* TranslateToColorTable() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Translate to a color table.
|
|
*
|
|
* This method will attempt to create a corresponding GDALColorTable from
|
|
* this raster attribute table.
|
|
*
|
|
* This method is the same as the C function GDALRATTranslateToColorTable().
|
|
*
|
|
* @param nEntryCount The number of entries to produce (0 to nEntryCount-1), or -1 to auto-determine the number of entries.
|
|
*
|
|
* @return the generated color table or NULL on failure.
|
|
*/
|
|
|
|
GDALColorTable *GDALRasterAttributeTable::TranslateToColorTable(
|
|
int nEntryCount )
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Establish which fields are red, green, blue and alpha. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iRed, iGreen, iBlue, iAlpha;
|
|
|
|
iRed = GetColOfUsage( GFU_Red );
|
|
iGreen = GetColOfUsage( GFU_Green );
|
|
iBlue = GetColOfUsage( GFU_Blue );
|
|
iAlpha = GetColOfUsage( GFU_Alpha );
|
|
|
|
if( iRed == -1 || iGreen == -1 || iBlue == -1 )
|
|
return NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* If we aren't given an explicit number of values to scan for, */
|
|
/* search for the maximum "max" value. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( nEntryCount == -1 )
|
|
{
|
|
int iRow;
|
|
int iMaxCol;
|
|
|
|
iMaxCol = GetColOfUsage( GFU_Max );
|
|
if( iMaxCol == -1 )
|
|
iMaxCol = GetColOfUsage( GFU_MinMax );
|
|
|
|
if( iMaxCol == -1 || GetRowCount() == 0 )
|
|
return NULL;
|
|
|
|
for( iRow = 0; iRow < GetRowCount(); iRow++ )
|
|
nEntryCount = MAX(nEntryCount,GetValueAsInt(iRow,iMaxCol)+1);
|
|
|
|
if( nEntryCount < 0 )
|
|
return NULL;
|
|
|
|
// restrict our number of entries to something vaguely sensible
|
|
nEntryCount = MIN(65535,nEntryCount);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Assign values to color table. */
|
|
/* -------------------------------------------------------------------- */
|
|
GDALColorTable *poCT = new GDALColorTable();
|
|
int iEntry;
|
|
|
|
for( iEntry = 0; iEntry < nEntryCount; iEntry++ )
|
|
{
|
|
GDALColorEntry sColor;
|
|
int iRow = GetRowOfValue( iEntry );
|
|
|
|
if( iRow == -1 )
|
|
{
|
|
sColor.c1 = sColor.c2 = sColor.c3 = sColor.c4 = 0;
|
|
}
|
|
else
|
|
{
|
|
sColor.c1 = (short) GetValueAsInt( iRow, iRed );
|
|
sColor.c2 = (short) GetValueAsInt( iRow, iGreen );
|
|
sColor.c3 = (short) GetValueAsInt( iRow, iBlue );
|
|
if( iAlpha == -1 )
|
|
sColor.c4 = 255;
|
|
else
|
|
sColor.c4 = (short) GetValueAsInt( iRow, iAlpha );
|
|
}
|
|
|
|
poCT->SetColorEntry( iEntry, &sColor );
|
|
}
|
|
|
|
return poCT;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATInitializeFromColorTable() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Translate to a color table.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::TranslateToColorTable()
|
|
*/
|
|
GDALColorTableH CPL_STDCALL
|
|
GDALRATTranslateToColorTable( GDALRasterAttributeTableH hRAT,
|
|
int nEntryCount )
|
|
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATTranslateToColorTable", NULL );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->
|
|
TranslateToColorTable( nEntryCount );
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* DumpReadable() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Dump RAT in readable form.
|
|
*
|
|
* Currently the readable form is the XML encoding ... only barely
|
|
* readable.
|
|
*
|
|
* This method is the same as the C function GDALRATDumpReadable().
|
|
*
|
|
* @param fp file to dump to or NULL for stdout.
|
|
*/
|
|
|
|
void GDALRasterAttributeTable::DumpReadable( FILE * fp )
|
|
|
|
{
|
|
CPLXMLNode *psTree = Serialize();
|
|
char *pszXMLText = CPLSerializeXMLTree( psTree );
|
|
|
|
CPLDestroyXMLNode( psTree );
|
|
|
|
if( fp == NULL )
|
|
fp = stdout;
|
|
|
|
fprintf( fp, "%s\n", pszXMLText );
|
|
|
|
CPLFree( pszXMLText );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATDumpReadable() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Dump RAT in readable form.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::DumpReadable()
|
|
*/
|
|
void CPL_STDCALL
|
|
GDALRATDumpReadable( GDALRasterAttributeTableH hRAT, FILE *fp )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hRAT, "GDALRATDumpReadable" );
|
|
|
|
((GDALRasterAttributeTable *) hRAT)->DumpReadable( fp );
|
|
}
|
|
|
|
|
|
/* \class GDALDefaultRasterAttributeTable
|
|
*
|
|
* An implementation of GDALRasterAttributeTable that keeps
|
|
* all data in memory. This is the same as the implementation
|
|
* of GDALRasterAttributeTable in GDAL <= 1.10.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* GDALDefaultRasterAttributeTable() */
|
|
/* */
|
|
/* Simple initialization constructor. */
|
|
/************************************************************************/
|
|
|
|
//! Construct empty table.
|
|
|
|
GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
|
|
|
|
{
|
|
bColumnsAnalysed = FALSE;
|
|
nMinCol = -1;
|
|
nMaxCol = -1;
|
|
bLinearBinning = FALSE;
|
|
dfRow0Min = -0.5;
|
|
dfBinSize = 1.0;
|
|
nRowCount = 0;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALCreateRasterAttributeTable() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Construct empty table.
|
|
*
|
|
* This function is the same as the C++ method GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
|
|
*/
|
|
GDALRasterAttributeTableH CPL_STDCALL GDALCreateRasterAttributeTable()
|
|
|
|
{
|
|
return (GDALRasterAttributeTableH) (new GDALDefaultRasterAttributeTable());
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALDefaultRasterAttributeTable() */
|
|
/************************************************************************/
|
|
|
|
//! Copy constructor.
|
|
|
|
GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable(
|
|
const GDALDefaultRasterAttributeTable &oOther )
|
|
|
|
{
|
|
// We have tried to be careful to allow wholesale assignment
|
|
*this = oOther;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~GDALDefaultRasterAttributeTable() */
|
|
/* */
|
|
/* All magic done by magic by the container destructors. */
|
|
/************************************************************************/
|
|
|
|
GDALDefaultRasterAttributeTable::~GDALDefaultRasterAttributeTable()
|
|
|
|
{
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALDestroyRasterAttributeTable() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Destroys a RAT.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::~GDALRasterAttributeTable()
|
|
*/
|
|
void CPL_STDCALL
|
|
GDALDestroyRasterAttributeTable( GDALRasterAttributeTableH hRAT )
|
|
|
|
{
|
|
if( hRAT != NULL )
|
|
delete static_cast<GDALRasterAttributeTable *>(hRAT);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* AnalyseColumns() */
|
|
/* */
|
|
/* Internal method to work out which column to use for various */
|
|
/* tasks. */
|
|
/************************************************************************/
|
|
|
|
void GDALDefaultRasterAttributeTable::AnalyseColumns()
|
|
|
|
{
|
|
bColumnsAnalysed = TRUE;
|
|
|
|
nMinCol = GetColOfUsage( GFU_Min );
|
|
if( nMinCol == -1 )
|
|
nMinCol = GetColOfUsage( GFU_MinMax );
|
|
|
|
nMaxCol = GetColOfUsage( GFU_Max );
|
|
if( nMaxCol == -1 )
|
|
nMaxCol = GetColOfUsage( GFU_MinMax );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetColumnCount() */
|
|
/************************************************************************/
|
|
|
|
int GDALDefaultRasterAttributeTable::GetColumnCount() const
|
|
|
|
{
|
|
return aoFields.size();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetColumnCount() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Fetch table column count.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetColumnCount()
|
|
*/
|
|
int CPL_STDCALL GDALRATGetColumnCount( GDALRasterAttributeTableH hRAT )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetColumnCount", 0 );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetColumnCount();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetNameOfCol() */
|
|
/************************************************************************/
|
|
|
|
const char *GDALDefaultRasterAttributeTable::GetNameOfCol( int iCol ) const
|
|
|
|
{
|
|
if( iCol < 0 || iCol >= (int) aoFields.size() )
|
|
return "";
|
|
|
|
else
|
|
return aoFields[iCol].sName;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetNameOfCol() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Fetch name of indicated column.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetNameOfCol()
|
|
*/
|
|
const char *CPL_STDCALL GDALRATGetNameOfCol( GDALRasterAttributeTableH hRAT,
|
|
int iCol )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetNameOfCol", NULL );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetNameOfCol( iCol );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetUsageOfCol() */
|
|
/************************************************************************/
|
|
|
|
GDALRATFieldUsage GDALDefaultRasterAttributeTable::GetUsageOfCol( int iCol ) const
|
|
|
|
{
|
|
if( iCol < 0 || iCol >= (int) aoFields.size() )
|
|
return GFU_Generic;
|
|
|
|
else
|
|
return aoFields[iCol].eUsage;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetUsageOfCol() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Fetch column usage value.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetUsageOfColetNameOfCol()
|
|
*/
|
|
GDALRATFieldUsage CPL_STDCALL
|
|
GDALRATGetUsageOfCol( GDALRasterAttributeTableH hRAT, int iCol )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetUsageOfCol", GFU_Generic );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetUsageOfCol( iCol );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetTypeOfCol() */
|
|
/************************************************************************/
|
|
|
|
GDALRATFieldType GDALDefaultRasterAttributeTable::GetTypeOfCol( int iCol ) const
|
|
|
|
{
|
|
if( iCol < 0 || iCol >= (int) aoFields.size() )
|
|
return GFT_Integer;
|
|
|
|
else
|
|
return aoFields[iCol].eType;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetTypeOfCol() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Fetch column type.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetTypeOfCol()
|
|
*/
|
|
GDALRATFieldType CPL_STDCALL
|
|
GDALRATGetTypeOfCol( GDALRasterAttributeTableH hRAT, int iCol )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetTypeOfCol", GFT_Integer );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetTypeOfCol( iCol );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetColOfUsage() */
|
|
/************************************************************************/
|
|
|
|
int GDALDefaultRasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) const
|
|
|
|
{
|
|
unsigned int i;
|
|
|
|
for( i = 0; i < aoFields.size(); i++ )
|
|
{
|
|
if( aoFields[i].eUsage == eUsage )
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetColOfUsage() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Fetch column index for given usage.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetColOfUsage()
|
|
*/
|
|
int CPL_STDCALL
|
|
GDALRATGetColOfUsage( GDALRasterAttributeTableH hRAT,
|
|
GDALRATFieldUsage eUsage )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetColOfUsage", 0 );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetColOfUsage( eUsage );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetRowCount() */
|
|
/************************************************************************/
|
|
|
|
int GDALDefaultRasterAttributeTable::GetRowCount() const
|
|
|
|
{
|
|
return (int) nRowCount;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetUsageOfCol() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Fetch row count.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetRowCount()
|
|
*/
|
|
int CPL_STDCALL
|
|
GDALRATGetRowCount( GDALRasterAttributeTableH hRAT )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetRowCount", 0 );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetRowCount();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetValueAsString() */
|
|
/************************************************************************/
|
|
|
|
const char *
|
|
GDALDefaultRasterAttributeTable::GetValueAsString( int iRow, int iField ) const
|
|
|
|
{
|
|
if( iField < 0 || iField >= (int) aoFields.size() )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iField (%d) out of range.", iField );
|
|
|
|
return "";
|
|
}
|
|
|
|
if( iRow < 0 || iRow >= nRowCount )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iRow (%d) out of range.", iRow );
|
|
|
|
return "";
|
|
}
|
|
|
|
switch( aoFields[iField].eType )
|
|
{
|
|
case GFT_Integer:
|
|
{
|
|
((GDALDefaultRasterAttributeTable *) this)->
|
|
osWorkingResult.Printf( "%d", aoFields[iField].anValues[iRow] );
|
|
return osWorkingResult;
|
|
}
|
|
|
|
case GFT_Real:
|
|
{
|
|
((GDALDefaultRasterAttributeTable *) this)->
|
|
osWorkingResult.Printf( "%.16g", aoFields[iField].adfValues[iRow]);
|
|
return osWorkingResult;
|
|
}
|
|
|
|
case GFT_String:
|
|
{
|
|
return aoFields[iField].aosValues[iRow];
|
|
}
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetValueAsString() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Fetch field value as a string.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsString()
|
|
*/
|
|
const char * CPL_STDCALL
|
|
GDALRATGetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsString", NULL );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetValueAsString(iRow, iField);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetValueAsInt() */
|
|
/************************************************************************/
|
|
|
|
int
|
|
GDALDefaultRasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
|
|
|
|
{
|
|
if( iField < 0 || iField >= (int) aoFields.size() )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iField (%d) out of range.", iField );
|
|
|
|
return 0;
|
|
}
|
|
|
|
if( iRow < 0 || iRow >= nRowCount )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iRow (%d) out of range.", iRow );
|
|
|
|
return 0;
|
|
}
|
|
|
|
switch( aoFields[iField].eType )
|
|
{
|
|
case GFT_Integer:
|
|
return aoFields[iField].anValues[iRow];
|
|
|
|
case GFT_Real:
|
|
return (int) aoFields[iField].adfValues[iRow];
|
|
|
|
case GFT_String:
|
|
return atoi( aoFields[iField].aosValues[iRow].c_str() );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetValueAsInt() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Fetch field value as a integer.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsInt()
|
|
*/
|
|
int CPL_STDCALL
|
|
GDALRATGetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsInt", 0 );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetValueAsInt( iRow, iField );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetValueAsDouble() */
|
|
/************************************************************************/
|
|
|
|
double
|
|
GDALDefaultRasterAttributeTable::GetValueAsDouble( int iRow, int iField ) const
|
|
|
|
{
|
|
if( iField < 0 || iField >= (int) aoFields.size() )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iField (%d) out of range.", iField );
|
|
|
|
return 0;
|
|
}
|
|
|
|
if( iRow < 0 || iRow >= nRowCount )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iRow (%d) out of range.", iRow );
|
|
|
|
return 0;
|
|
}
|
|
|
|
switch( aoFields[iField].eType )
|
|
{
|
|
case GFT_Integer:
|
|
return aoFields[iField].anValues[iRow];
|
|
|
|
case GFT_Real:
|
|
return aoFields[iField].adfValues[iRow];
|
|
|
|
case GFT_String:
|
|
return CPLAtof( aoFields[iField].aosValues[iRow].c_str() );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATGetValueAsDouble() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Fetch field value as a double.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::GetValueAsDouble()
|
|
*/
|
|
double CPL_STDCALL
|
|
GDALRATGetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATGetValueAsDouble", 0 );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->GetValueAsDouble(iRow,iField);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetRowCount() */
|
|
/************************************************************************/
|
|
|
|
void GDALDefaultRasterAttributeTable::SetRowCount( int nNewCount )
|
|
|
|
{
|
|
if( nNewCount == nRowCount )
|
|
return;
|
|
|
|
unsigned int iField;
|
|
for( iField = 0; iField < aoFields.size(); iField++ )
|
|
{
|
|
switch( aoFields[iField].eType )
|
|
{
|
|
case GFT_Integer:
|
|
aoFields[iField].anValues.resize( nNewCount );
|
|
break;
|
|
|
|
case GFT_Real:
|
|
aoFields[iField].adfValues.resize( nNewCount );
|
|
break;
|
|
|
|
case GFT_String:
|
|
aoFields[iField].aosValues.resize( nNewCount );
|
|
break;
|
|
}
|
|
}
|
|
|
|
nRowCount = nNewCount;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetValue() */
|
|
/************************************************************************/
|
|
|
|
void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
|
|
const char *pszValue )
|
|
|
|
{
|
|
if( iField < 0 || iField >= (int) aoFields.size() )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iField (%d) out of range.", iField );
|
|
|
|
return;
|
|
}
|
|
|
|
if( iRow == nRowCount )
|
|
SetRowCount( nRowCount+1 );
|
|
|
|
if( iRow < 0 || iRow >= nRowCount )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iRow (%d) out of range.", iRow );
|
|
|
|
return;
|
|
}
|
|
|
|
switch( aoFields[iField].eType )
|
|
{
|
|
case GFT_Integer:
|
|
aoFields[iField].anValues[iRow] = atoi(pszValue);
|
|
break;
|
|
|
|
case GFT_Real:
|
|
aoFields[iField].adfValues[iRow] = CPLAtof(pszValue);
|
|
break;
|
|
|
|
case GFT_String:
|
|
aoFields[iField].aosValues[iRow] = pszValue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATSetValueAsString() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Set field value from string.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
|
|
*/
|
|
void CPL_STDCALL
|
|
GDALRATSetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField,
|
|
const char *pszValue )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsString" );
|
|
|
|
((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, pszValue );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetValue() */
|
|
/************************************************************************/
|
|
|
|
void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
|
|
int nValue )
|
|
|
|
{
|
|
if( iField < 0 || iField >= (int) aoFields.size() )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iField (%d) out of range.", iField );
|
|
|
|
return;
|
|
}
|
|
|
|
if( iRow == nRowCount )
|
|
SetRowCount( nRowCount+1 );
|
|
|
|
if( iRow < 0 || iRow >= nRowCount )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iRow (%d) out of range.", iRow );
|
|
|
|
return;
|
|
}
|
|
|
|
switch( aoFields[iField].eType )
|
|
{
|
|
case GFT_Integer:
|
|
aoFields[iField].anValues[iRow] = nValue;
|
|
break;
|
|
|
|
case GFT_Real:
|
|
aoFields[iField].adfValues[iRow] = nValue;
|
|
break;
|
|
|
|
case GFT_String:
|
|
{
|
|
char szValue[100];
|
|
|
|
sprintf( szValue, "%d", nValue );
|
|
aoFields[iField].aosValues[iRow] = szValue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATSetValueAsInt() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Set field value from integer.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
|
|
*/
|
|
void CPL_STDCALL
|
|
GDALRATSetValueAsInt( GDALRasterAttributeTableH hRAT, int iRow, int iField,
|
|
int nValue )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsInt" );
|
|
|
|
((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, nValue);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetValue() */
|
|
/************************************************************************/
|
|
|
|
void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
|
|
double dfValue )
|
|
|
|
{
|
|
if( iField < 0 || iField >= (int) aoFields.size() )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iField (%d) out of range.", iField );
|
|
|
|
return;
|
|
}
|
|
|
|
if( iRow == nRowCount )
|
|
SetRowCount( nRowCount+1 );
|
|
|
|
if( iRow < 0 || iRow >= nRowCount )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"iRow (%d) out of range.", iRow );
|
|
|
|
return;
|
|
}
|
|
|
|
switch( aoFields[iField].eType )
|
|
{
|
|
case GFT_Integer:
|
|
aoFields[iField].anValues[iRow] = (int) dfValue;
|
|
break;
|
|
|
|
case GFT_Real:
|
|
aoFields[iField].adfValues[iRow] = dfValue;
|
|
break;
|
|
|
|
case GFT_String:
|
|
{
|
|
char szValue[100];
|
|
|
|
CPLsprintf( szValue, "%.15g", dfValue );
|
|
aoFields[iField].aosValues[iRow] = szValue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATSetValueAsDouble() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Set field value from double.
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::SetValue()
|
|
*/
|
|
void CPL_STDCALL
|
|
GDALRATSetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField,
|
|
double dfValue )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hRAT, "GDALRATSetValueAsDouble" );
|
|
|
|
((GDALRasterAttributeTable *) hRAT)->SetValue( iRow, iField, dfValue );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ChangesAreWrittenToFile() */
|
|
/************************************************************************/
|
|
|
|
int GDALDefaultRasterAttributeTable::ChangesAreWrittenToFile()
|
|
{
|
|
// GDALRasterBand.SetDefaultRAT needs to be called on instances of
|
|
// GDALDefaultRasterAttributeTable since changes are just in-memory
|
|
return FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATChangesAreWrittenToFile() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Determine whether changes made to this RAT are reflected directly in the dataset
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::ChangesAreWrittenToFile()
|
|
*/
|
|
int CPL_STDCALL
|
|
GDALRATChangesAreWrittenToFile( GDALRasterAttributeTableH hRAT )
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATChangesAreWrittenToFile", FALSE );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->ChangesAreWrittenToFile();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetRowOfValue() */
|
|
/************************************************************************/
|
|
|
|
int GDALDefaultRasterAttributeTable::GetRowOfValue( double dfValue ) const
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Handle case of regular binning. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( bLinearBinning )
|
|
{
|
|
int iBin = (int) floor((dfValue - dfRow0Min) / dfBinSize);
|
|
if( iBin < 0 || iBin >= nRowCount )
|
|
return -1;
|
|
else
|
|
return iBin;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Do we have any information? */
|
|
/* -------------------------------------------------------------------- */
|
|
const GDALRasterAttributeField *poMin, *poMax;
|
|
|
|
if( !bColumnsAnalysed )
|
|
((GDALDefaultRasterAttributeTable *) this)->AnalyseColumns();
|
|
|
|
if( nMinCol == -1 && nMaxCol == -1 )
|
|
return -1;
|
|
|
|
if( nMinCol != -1 )
|
|
poMin = &(aoFields[nMinCol]);
|
|
else
|
|
poMin = NULL;
|
|
|
|
if( nMaxCol != -1 )
|
|
poMax = &(aoFields[nMaxCol]);
|
|
else
|
|
poMax = NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Search through rows for match. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iRow;
|
|
|
|
for( iRow = 0; iRow < nRowCount; iRow++ )
|
|
{
|
|
if( poMin != NULL )
|
|
{
|
|
if( poMin->eType == GFT_Integer )
|
|
{
|
|
while( iRow < nRowCount && dfValue < poMin->anValues[iRow] )
|
|
iRow++;
|
|
}
|
|
else if( poMin->eType == GFT_Real )
|
|
{
|
|
while( iRow < nRowCount && dfValue < poMin->adfValues[iRow] )
|
|
iRow++;
|
|
}
|
|
|
|
if( iRow == nRowCount )
|
|
break;
|
|
}
|
|
|
|
if( poMax != NULL )
|
|
{
|
|
if( (poMax->eType == GFT_Integer
|
|
&& dfValue > poMax->anValues[iRow] )
|
|
|| (poMax->eType == GFT_Real
|
|
&& dfValue > poMax->adfValues[iRow] ) )
|
|
continue;
|
|
}
|
|
|
|
return iRow;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetRowOfValue() */
|
|
/* */
|
|
/* Int arg for now just converted to double. Perhaps we will */
|
|
/* handle this in a special way some day? */
|
|
/************************************************************************/
|
|
|
|
int GDALDefaultRasterAttributeTable::GetRowOfValue( int nValue ) const
|
|
|
|
{
|
|
return GetRowOfValue( (double) nValue );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetLinearBinning() */
|
|
/************************************************************************/
|
|
|
|
CPLErr GDALDefaultRasterAttributeTable::SetLinearBinning( double dfRow0MinIn,
|
|
double dfBinSizeIn )
|
|
|
|
{
|
|
bLinearBinning = TRUE;
|
|
dfRow0Min = dfRow0MinIn;
|
|
dfBinSize = dfBinSizeIn;
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetLinearBinning() */
|
|
/************************************************************************/
|
|
|
|
int GDALDefaultRasterAttributeTable::GetLinearBinning( double *pdfRow0Min,
|
|
double *pdfBinSize ) const
|
|
|
|
{
|
|
if( !bLinearBinning )
|
|
return FALSE;
|
|
|
|
*pdfRow0Min = dfRow0Min;
|
|
*pdfBinSize = dfBinSize;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CreateColumn() */
|
|
/************************************************************************/
|
|
|
|
CPLErr GDALDefaultRasterAttributeTable::CreateColumn( const char *pszFieldName,
|
|
GDALRATFieldType eFieldType,
|
|
GDALRATFieldUsage eFieldUsage )
|
|
|
|
{
|
|
int iNewField = aoFields.size();
|
|
|
|
aoFields.resize( iNewField+1 );
|
|
|
|
aoFields[iNewField].sName = pszFieldName;
|
|
|
|
// color columns should be int 0..255
|
|
if( ( eFieldUsage == GFU_Red ) || ( eFieldUsage == GFU_Green ) ||
|
|
( eFieldUsage == GFU_Blue ) || ( eFieldUsage == GFU_Alpha ) )
|
|
{
|
|
eFieldType = GFT_Integer;
|
|
}
|
|
aoFields[iNewField].eType = eFieldType;
|
|
aoFields[iNewField].eUsage = eFieldUsage;
|
|
|
|
if( eFieldType == GFT_Integer )
|
|
aoFields[iNewField].anValues.resize( nRowCount );
|
|
else if( eFieldType == GFT_Real )
|
|
aoFields[iNewField].adfValues.resize( nRowCount );
|
|
else if( eFieldType == GFT_String )
|
|
aoFields[iNewField].aosValues.resize( nRowCount );
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Clone() */
|
|
/************************************************************************/
|
|
|
|
GDALDefaultRasterAttributeTable *GDALDefaultRasterAttributeTable::Clone() const
|
|
|
|
{
|
|
return new GDALDefaultRasterAttributeTable( *this );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATClone() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Copy Raster Attribute Table
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::Clone()
|
|
*/
|
|
GDALRasterAttributeTableH CPL_STDCALL
|
|
GDALRATClone( GDALRasterAttributeTableH hRAT )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATClone", NULL );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->Clone();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRATSerializeJSON() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Serialize Raster Attribute Table in Json format
|
|
*
|
|
* This function is the same as the C++ method GDALRasterAttributeTable::SerializeJSON()
|
|
*/
|
|
void* CPL_STDCALL
|
|
GDALRATSerializeJSON( GDALRasterAttributeTableH hRAT )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hRAT, "GDALRATSerializeJSON", NULL );
|
|
|
|
return ((GDALRasterAttributeTable *) hRAT)->SerializeJSON();
|
|
}
|