24#include "qgsogrprovider.h"
35using namespace Qt::StringLiterals;
38std::once_flag usageInformationLoaderFlag;
39QHash<Qgis::RasterAttributeTableFieldUsage, QgsRasterAttributeTable::UsageInformation> QgsRasterAttributeTable::sUsageInformation;
51 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
64 for (
int idx = 0; idx < mFields.count(); ++idx )
66 const Field f { mFields.at( idx ) };
97 for (
Field &f : mFields )
135 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
147 QList<Qgis::RasterAttributeTableFieldUsage>
usages;
150 usages.push_back( field.usage );
156QList<int> QgsRasterAttributeTable::intUsages()
const
161 usages.push_back(
static_cast<int>( field.usage ) );
169 QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
172 &&
row < mData.count()
177 const QVariantList rowData = mData.at(
row );
198 QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
199 const QVariantList rowData = mData.at(
row );
240 for (
const QVariantList &
row : std::as_const( mData ) )
243 for (
const auto &cell : std::as_const(
row ) )
245 attributes.append( cell );
249 features.append( feature );
266 const int realPos { std::clamp( position, 0,
static_cast<int>( mFields.count() ) ) };
268 if ( field.
name.isEmpty() )
272 *errorMessage = tr(
"Field name must not be empty." );
285 *errorMessage = tr(
"A field with name '%1' already exists." ).arg( field.
name );
291 static const QList<Qgis::RasterAttributeTableFieldUsage> uniqueUsages {
315 *errorMessage = tr(
"A field with unique usage '%1' already exists." ).arg(
usageName( field.
usage ) );
320 mFields.insert( realPos, field );
322 for (
auto it = mData.begin(); it != mData.end(); ++it )
326 switch ( field.
type )
328 case QMetaType::Type::QChar:
329 case QMetaType::Type::Int:
330 case QMetaType::Type::UInt:
331 case QMetaType::Type::LongLong:
332 case QMetaType::Type::ULongLong:
333 case QMetaType::Type::Double:
337 defaultValue = QString();
339 it->insert( realPos, defaultValue );
370 const QList<Qgis::RasterAttributeTableFieldUsage> colors {
373 int idx { position };
387 if ( fieldIndex < 0 || fieldIndex >=
fields().count() )
398 mFields[fieldIndex].
usage = usage;
410 *errorMessage = tr(
"A color ramp can only be added to an athematic attribute table." );
413 const QList<Qgis::RasterAttributeTableFieldUsage> colors {
423 int idx { position };
437 return insertField(
static_cast<int>( mFields.count() ), name, usage,
type, errorMessage );
447 return insertField(
static_cast<int>( mFields.count() ), field, errorMessage );
452 const auto toRemove { std::find_if( mFields.begin(), mFields.end(), [&name](
Field &f ) ->
bool { return f.name == name; } ) };
454 if ( toRemove != mFields.end() )
456 const int idx {
static_cast<int>( std::distance( mFields.begin(), toRemove ) ) };
457 mFields.erase( toRemove );
458 for (
auto it = mData.begin(); it != mData.end(); ++it )
469 *errorMessage = tr(
"A field with name '%1' was not found." ).arg( name );
476 const int realPos { std::clamp( position, 0,
static_cast<int>( mData.count() ) ) };
478 if ( rowData.size() != mFields.size() )
482 *errorMessage = tr(
"Row element count differs from field count (%1)." ).arg( mFields.size() );
487 QVariantList dataValid;
489 for (
int idx = 0; idx < mFields.count(); ++idx )
491 const QMetaType::Type
type = mFields.at( idx ).type;
492 QVariant cell( rowData[idx] );
493 if (
type == QMetaType::Type::QDateTime && cell.toString().isEmpty() )
495 dataValid.append( QVariant() );
497 else if ( !cell.canConvert(
type ) || !cell.convert(
type ) )
501 *errorMessage = tr(
"Row data at column %1 cannot be converted to field type (%2)." ).arg( idx ).arg( QVariant::typeToName(
type ) );
507 dataValid.append( cell );
511 mData.insert( realPos, dataValid );
518 if ( position >= mData.count() || position < 0 || mData.isEmpty() )
522 *errorMessage = tr(
"Position is not valid or the table is empty." );
526 mData.removeAt( position );
533 return insertRow(
static_cast<int>( mData.count() ),
data, errorMessage );
544 std::unique_ptr<QgsVectorFileWriter> writer;
547 QString cleanedPath { path };
548 if ( path.endsWith( u
".dbf"_s, Qt::CaseSensitivity::CaseInsensitive ) )
550 cleanedPath.chop( 4 );
557 cleanedPath.append( u
".dbf"_s );
564 *errorMessage = tr(
"Error creating Raster Attribute Table table: %1." ).arg( writer->errorMessage() );
570 bool result { writer->addFeatures( features ) };
576 *errorMessage = tr(
"Error creating Raster Attribute Table table: could not add rows." );
581 result = writer->flushBuffer();
585 mFilePath = cleanedPath;
595 if ( !ratDbfSource.isValid() )
599 *errorMessage = tr(
"Error reading Raster Attribute Table table from file: invalid layer." );
604 QList<Field> oldFields = mFields;
605 QList<QVariantList> oldData = mData;
610 bool hasValueField {
false };
611 for (
const QgsField &field : ratDbfSource.fields() )
614 QMetaType::Type
type { field.type() };
616 if (
type == QMetaType::Type::LongLong
619 type = QMetaType::Type::Int;
624 hasValueField =
true;
637 if ( ! hasValueField && mFields.count() > 1 && ( mFields.at( 0 ).type == QMetaType::Type::Int || mFields.at( 0 ).type == QMetaType::Type::QChar || mFields.at( 0 ).type == QMetaType::Type::UInt || mFields.at( 0 ).type == QMetaType::Type::LongLong || mFields.at( 0 ).type == QMetaType::Type::ULongLong ) )
642 const int fieldCount {
static_cast<int>( ratDbfSource.fields().count() ) };
651 *errorMessage = tr(
"Error reading Raster Attribute Table table from file: number of fields and number of attributes do not match." );
671 if ( mFields.isEmpty() )
673 errors.push_back( tr(
"The attribute table has no fields." ) );
676 if ( mData.isEmpty() )
678 errors.push_back( tr(
"The attribute table has no rows." ) );
681 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
684 if ( !isMinMax && !isValueRamp )
686 errors.push_back( tr(
"The attribute table has no MinMax nor a pair of Min and Max fields." ) );
698 errors.push_back( tr(
"The attribute table has some but not all the fields required for color definition (Red, Green, Blue)." ) );
717 errors.push_back( tr(
"The attribute table has some but not all the fields required for color ramp definition (RedMin, GreenMin, BlueMin, RedMax, GreenMax, BlueMax)." ) );
719 else if ( !isValueRamp )
721 errors.push_back( tr(
"The attribute table has all the fields required for color ramp definition (RedMin, GreenMin, BlueMin, RedMax, GreenMax, BlueMax) but no Min and Max field." ) );
725 if ( errorMessage && !errors.isEmpty() )
727 *errorMessage = errors.join( QChar(
'\n' ) );
730 return errors.isEmpty();
740 for (
const Field &f : std::as_const( mFields ) )
742 if ( f.name == name )
760 QList<QgsRasterAttributeTable::Field> result;
761 for (
const Field &f : std::as_const( mFields ) )
763 if ( f.usage == fieldUsage )
765 result.push_back( f );
778 QVariant newVal =
value;
779 if ( column >= mFields.length() || !
value.canConvert( mFields.at( column ).type ) || !newVal.convert( mFields.at( column ).type ) )
784 const QVariant oldVal = mData[
row][column];
786 if ( newVal != oldVal )
788 mData[
row][column] = newVal;
801 return mData[
row][column];
806 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
819 double min { std::numeric_limits<double>::max() };
820 for (
int rowIdx = 0; rowIdx < mData.count(); ++rowIdx )
822 min = std::min( min,
value( rowIdx, fieldIdx ).toDouble( &ok ) );
825 return std::numeric_limits<double>::quiet_NaN();
829 if ( fieldIdx == -1 || !ok )
831 return std::numeric_limits<double>::quiet_NaN();
841 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
854 double max { std::numeric_limits<double>::lowest() };
855 for (
int rowIdx = 0; rowIdx < mData.count(); ++rowIdx )
857 max = std::max( max,
value( rowIdx, fieldIdx ).toDouble( &ok ) );
860 return std::numeric_limits<double>::quiet_NaN();
864 if ( fieldIdx == -1 || !ok )
866 return std::numeric_limits<double>::quiet_NaN();
878 return QVariantList();
881 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
886 for (
int rowIdx = 0; rowIdx < mData.count(); ++rowIdx )
889 if ( matchValue ==
value( rowIdx, colIdx ).toDouble( &ok ) && ok )
891 return mData.at( rowIdx );
899 for (
int rowIdx = 0; rowIdx < mData.count(); ++rowIdx )
902 if ( matchValue >=
value( rowIdx, minColIdx ).toDouble( &ok ) && ok )
904 if ( matchValue <
value( rowIdx, maxColIdx ).toDouble( &ok ) && ok )
906 return mData.at( rowIdx );
911 return QVariantList();
916 static const QStringList minValueNames { {
924 static const QStringList maxValueNames { {
932 const QString fieldLower { name.toLower() };
934 if (
type == QMetaType::Type::Double ||
type == QMetaType::Type::Int ||
type == QMetaType::Type::UInt ||
type == QMetaType::Type::LongLong ||
type == QMetaType::Type::ULongLong )
936 if ( minValueNames.contains( fieldLower ) )
940 else if ( maxValueNames.contains( fieldLower ) )
944 else if ( fieldLower ==
"value"_L1 )
948 else if ( fieldLower ==
"count"_L1 )
954 else if (
type != QMetaType::Type::Double )
956 if ( fieldLower.contains(
"red" ) || fieldLower ==
"r"_L1 )
958 if ( fieldLower.contains(
"min" ) )
962 else if ( fieldLower.contains(
"max" ) )
971 else if ( fieldLower.contains(
"green" ) || fieldLower ==
"g"_L1 )
973 if ( fieldLower.contains(
"min" ) )
977 else if ( fieldLower.contains(
"max" ) )
986 else if ( fieldLower.contains(
"blue" ) || fieldLower ==
"b"_L1 )
988 if ( fieldLower.contains(
"min" ) )
992 else if ( fieldLower.contains(
"max" ) )
1001 else if ( fieldLower.contains(
"alpha" ) || fieldLower ==
"a"_L1 )
1003 if ( fieldLower.contains(
"min" ) )
1007 else if ( fieldLower.contains(
"max" ) )
1020 if (
type == QMetaType::Type::QString )
1041 return tr(
"Green" );
1043 return tr(
"Blue" );
1045 return tr(
"Alpha" );
1047 return tr(
"Red Minimum" );
1049 return tr(
"Green Minimum" );
1051 return tr(
"Blue Minimum" );
1053 return tr(
"Alpha Minimum" );
1055 return tr(
"Red Maximum" );
1057 return tr(
"Green Maximum" );
1059 return tr(
"Blue Maximum" );
1061 return tr(
"Alpha Maximum" );
1063 return tr(
"Generic" );
1065 return tr(
"Name" );
1067 return tr(
"Pixel Count" );
1069 return tr(
"Maximum Count" );
1071 return tr(
"Value" );
1073 return tr(
"Minimum Value" );
1075 return tr(
"Maximum Value" );
1082 static const QList<Qgis::RasterAttributeTableFieldUsage> valueColorUsages { {
1099 return valueColorUsages;
1130 rat->
appendRow( QVariantList() << klass.value << klass.label << 0 << 0 << 0 << 255 );
1131 rat->
setColor(
static_cast<int>( rat->
data().length() - 1 ), klass.color );
1136 *bandNumber = palettedRenderer->inputBand();
1147 switch ( shaderFunction->colorRampType() )
1162 const QList<QgsColorRampShader::ColorRampItem> rampItems { shaderFunction->colorRampItemList() };
1163 if ( rampItems.size() > 1 )
1165 QColor color1 { rampItems.at( 0 ).color };
1166 QString label1 { rampItems.at( 0 ).label };
1167 QVariant value1( rampItems.at( 0 ).value );
1168 const int rampItemSize =
static_cast<int>( rampItems.size() );
1169 for (
int i = 1; i < rampItemSize; ++i )
1172 rat->
appendRow( QVariantList() << value1 << rampItem.
value << u
"%1 - %2"_s.arg( label1, rampItem.
label ) << 0 << 0 << 0 << 255 << 0 << 0 << 0 << 255 );
1173 rat->
setRamp(
static_cast<int>( rat->
data().length() - 1 ), color1, rampItem.
color );
1174 label1 = rampItem.
label;
1175 value1 = rampItem.
value;
1176 color1 = rampItem.
color;
1191 const QList<QgsColorRampShader::ColorRampItem> rampItems { shaderFunction->colorRampItemList() };
1192 if ( rampItems.size() > 1 )
1194 QColor color1 { rampItems.at( 0 ).color };
1195 QString label1 { rampItems.at( 0 ).label };
1196 QVariant value1( rampItems.at( 0 ).value );
1197 const int rampItemSize =
static_cast<int>( rampItems.size() );
1198 for (
int i = 1; i < rampItemSize; ++i )
1201 rat->
appendRow( QVariantList() << value1 << rampItem.
value << u
"%1 - %2"_s.arg( label1, rampItem.
label ) << 0 << 0 << 0 << 255 << 0 << 0 << 0 << 255 );
1202 rat->
setRamp(
static_cast<int>( rat->
data().length() - 1 ), color1, rampItem.
color );
1203 label1 = rampItem.
label;
1204 value1 = rampItem.
value;
1205 color1 = rampItem.
color;
1219 const QList<QgsColorRampShader::ColorRampItem> rampItems { shaderFunction->colorRampItemList() };
1222 rat->
appendRow( QVariantList() << rampItem.value << rampItem.label << 0 << 0 << 0 << 255 );
1223 rat->
setColor(
static_cast<int>( rat->
data().length() - 1 ), rampItem.color );
1231 *bandNumber = pseudoColorRenderer->inputBand();
1254 std::call_once( usageInformationLoaderFlag, [] {
1255 QgsRasterAttributeTable::sUsageInformation.insert(
1257 { tr(
"General Purpose Field" ),
false,
false,
false,
false,
true,
true, QList<QMetaType::Type>() << QMetaType::Type::QString << QMetaType::Type::Int << QMetaType::Type::LongLong << QMetaType::Type::Double }
1259 QgsRasterAttributeTable::sUsageInformation
1261 QgsRasterAttributeTable::sUsageInformation
1263 QgsRasterAttributeTable::sUsageInformation
1264 .insert(
Qgis::RasterAttributeTableFieldUsage::MinMax, { tr(
"Class Value (min=max)" ),
true,
true,
false,
false,
true,
false, QList<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::LongLong << QMetaType::Type::Double } );
1265 QgsRasterAttributeTable::sUsageInformation
1266 .insert(
Qgis::RasterAttributeTableFieldUsage::Min, { tr(
"Class Minimum Value" ),
true,
true,
false,
false,
true,
false, QList<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::LongLong << QMetaType::Type::Double } );
1267 QgsRasterAttributeTable::sUsageInformation
1268 .insert(
Qgis::RasterAttributeTableFieldUsage::Max, { tr(
"Class Maximum Value" ),
true,
true,
false,
false,
true,
false, QList<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::LongLong << QMetaType::Type::Double } );
1269 QgsRasterAttributeTable::sUsageInformation
1271 QgsRasterAttributeTable::sUsageInformation
1273 QgsRasterAttributeTable::sUsageInformation
1275 QgsRasterAttributeTable::sUsageInformation
1277 QgsRasterAttributeTable::sUsageInformation
1279 QgsRasterAttributeTable::sUsageInformation
1281 QgsRasterAttributeTable::sUsageInformation
1283 QgsRasterAttributeTable::sUsageInformation
1285 QgsRasterAttributeTable::sUsageInformation
1287 QgsRasterAttributeTable::sUsageInformation
1289 QgsRasterAttributeTable::sUsageInformation
1291 QgsRasterAttributeTable::sUsageInformation
1294 QgsRasterAttributeTable::sUsageInformation
1297 return QgsRasterAttributeTable::sUsageInformation;
1300void QgsRasterAttributeTable::setType()
1302 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1308QHash<int, QgsRasterAttributeTable::UsageInformation> QgsRasterAttributeTable::usageInformationInt()
1310 QHash<int, QgsRasterAttributeTable::UsageInformation> usageInfoInt;
1312 for (
auto it = usageInfo.cbegin(); it != usageInfo.cend(); ++it )
1314 usageInfoInt.insert(
static_cast<int>( it.key() ), it.value() );
1316 return usageInfoInt;
1327 QList<QgsRasterAttributeTable::MinMaxClass> classes;
1330 QgsDebugError(
"minMaxClasses was called on an invalid RAT" );
1334 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1338 QgsDebugError(
"minMaxClasses was called on a ramp raster" );
1344 Q_ASSERT( minMaxIndex >= 0 );
1346 int classificationIndex = classificationColumn;
1347 if ( classificationIndex >= 0 && classificationIndex < mFields.count() )
1349 const Field classificationField { mFields.at( classificationIndex ) };
1352 QgsDebugError(
"minMaxClasses was called with a classification column which is not suitable for classification" );
1356 else if ( classificationIndex == -1 )
1369 classificationIndex = minMaxIndex;
1372 else if ( classificationIndex >= mFields.count() )
1374 QgsDebugError(
"minMaxClasses was called with a classification column out of range" );
1378 if ( classificationIndex >= 0 )
1382 for (
const QVariantList &
row : std::as_const( mData ) )
1384 const QString label {
row.at( classificationIndex ).toString() };
1386 const double value {
row.at( minMaxIndex ).toDouble( &ok ) };
1390 QgsDebugError(
"minMaxClasses could not convert a MinMax value to double" );
1393 if ( labels.contains( label ) )
1395 classes[labels.indexOf( label )].minMaxValues.push_back(
value );
1399 labels.push_back( label );
1400 classes.push_back( { label, {
value },
color( rowIdx ) } );
1411 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1414 const bool isRange { minIdx >= 0 && maxIdx >= 0 };
1416 int labelIdx { labelColumn };
1417 if ( labelColumn < 0
1418 || labelColumn >=
fields().count()
1424 if ( !mData.isEmpty() && ( minIdx >= 0 && maxIdx >= 0 ) )
1431 const double range { max - min };
1435 if ( !std::isnan( min ) && !std::isnan( max ) )
1437 const QList<QVariantList> dataCopy(
orderedRows() );
1440 for (
const Field &f : std::as_const( mFields ) )
1444 for (
const QVariantList &r : std::as_const( dataCopy ) )
1449 QColor lastColor {
ramp.color1() };
1451 if ( hasColorOrRamp )
1454 ramp.setColor2( orderedRat.
hasColor() ? orderedRat.
color(
static_cast<int>( orderedRat.
data().count() - 1 ) ) : orderedRat.
ramp(
static_cast<int>( orderedRat.
data().count() - 1 ) ).
color2() );
1458 auto labelFromField = [&](
int rowIdx ) -> QString {
1461 return u
"%L1 - %L2"_s.arg( orderedRat.
value( rowIdx, minIdx ).toDouble() ).arg( orderedRat.
value( rowIdx, maxIdx ).toDouble() );
1463 const QVariant val( orderedRat.
value( rowIdx, labelIdx ) );
1466 switch ( val.userType() )
1468 case QMetaType::Type::QChar:
1469 return QString( val.toChar() );
1470 case QMetaType::Type::Int:
1471 res = QLocale().toString( val.toInt( &ok ) );
1473 case QMetaType::Type::LongLong:
1474 res = QLocale().toString( val.toLongLong( &ok ) );
1476 case QMetaType::Type::UInt:
1477 res = QLocale().toString( val.toUInt( &ok ) );
1479 case QMetaType::Type::ULongLong:
1480 res = QLocale().toString( val.toULongLong( &ok ) );
1482 case QMetaType::Type::Double:
1483 res = QLocale().toString( val.toDouble( &ok ),
'g' );
1485 case QMetaType::Type::QString:
1487 return val.toString();
1489 return ok ? res : val.toString();
1495 if ( orderedRat.
hasColor() && isRange )
1497 labels.push_back( labelFromField( 0 ) );
1499 for (
int rowIdx = 1; rowIdx < orderedRat.
data().count(); ++rowIdx )
1501 const double offset { ( orderedRat.
value( rowIdx, minIdx ).toDouble() - min ) / range };
1502 const QColor
color { orderedRat.
color( rowIdx - 1 ) };
1504 labels.push_back( labelFromField( rowIdx ) );
1513 else if ( orderedRat.
hasRamp() && isRange )
1515 double prevOffset { 0 };
1516 labels.push_back( labelFromField( 0 ) );
1517 for (
int rowIdx = 1; rowIdx < orderedRat.
data().count(); ++rowIdx )
1519 labels.push_back( labelFromField( rowIdx ) );
1520 const int prevRowIdx { rowIdx - 1 };
1521 const double offset { ( ( orderedRat.
value( rowIdx, minIdx ).toDouble() + orderedRat.
value( prevRowIdx, maxIdx ).toDouble() ) / 2.0 - min ) / range };
1529 stops.append(
QgsGradientStop( offset + std::numeric_limits<double>::epsilon(), currentRamp.
color1() ) );
1531 prevOffset = offset;
1539 labels.push_back( labelFromField( 0 ) );
1541 for (
int rowIdx = 1; rowIdx < orderedRat.
data().count(); ++rowIdx )
1543 const int prevRowIdx { rowIdx - 1 };
1544 const double offset { ( ( orderedRat.
value( rowIdx, minIdx ).toDouble() + orderedRat.
value( prevRowIdx, maxIdx ).toDouble() ) / 2.0 - min ) / range };
1546 labels.push_back( labelFromField( rowIdx ) );
1553 ramp.setStops( stops );
1567 std::unique_ptr<QgsRasterRenderer> renderer;
1571 std::unique_ptr<QgsColorRamp>
ramp;
1574 ramp = std::make_unique<QgsRandomColorRamp>();
1577 if ( classes.isEmpty() )
1580 renderer = std::make_unique<QgsPalettedRasterRenderer>( provider, bandNumber, classes );
1584 auto pseudoColorRenderer = std::make_unique<QgsSingleBandPseudoColorRenderer>( provider, bandNumber );
1588 int labelColumn { classificationColumn };
1589 if ( labelColumn < 0 )
1591 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1593 if ( labelColumn < 0 )
1599 pseudoColorRenderer->setClassificationMin(
minimumValue() );
1600 pseudoColorRenderer->setClassificationMax(
maximumValue() );
1602 pseudoColorRenderer->createShader(
1605 if ( pseudoColorRenderer->shader() )
1607 pseudoColorRenderer->shader()->setMaximumValue(
maximumValue() );
1608 pseudoColorRenderer->shader()->setMinimumValue(
minimumValue() );
1614 const bool labelsAreUsable {
ramp->count() > 2 && labels.count() ==
ramp->count() - 1 };
1616 if ( labelsAreUsable )
1618 QList<QgsColorRampShader::ColorRampItem> newItemList;
1621 for (
const QString &label : std::as_const( labels ) )
1623 if ( stopIdx >=
ramp->count() - 2 )
1629 newItemList.push_back( item );
1634 newItemList.push_back( item );
1635 shaderFunction->setColorRampItemList( newItemList );
1639 renderer = std::move( pseudoColorRenderer );
1642 return renderer.release();
1647 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1650 const bool isRange { minIdx >= 0 && maxIdx >= 0 };
1651 QList<QVariantList> dataCopy( mData );
1655 std::sort( dataCopy.begin(), dataCopy.end(), [&](
const QVariantList &first,
const QVariantList &second ) ->
bool {
1656 return ( first.at( maxIdx ).toDouble() + first.at( minIdx ).toDouble() ) < ( second.at( maxIdx ).toDouble() + second.at( minIdx ).toDouble() );
1662 if ( minMaxIdx < 0 )
1668 std::sort( dataCopy.begin(), dataCopy.end(), [&](
const QVariantList &first,
const QVariantList &second ) ->
bool { return first.at( minMaxIdx ).toDouble() < second.at( minMaxIdx ).toDouble(); } );
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
@ Linear
Interpolates the color between two class breaks linearly.
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
RasterAttributeTableType
The RasterAttributeTableType enum represents the type of RAT.
@ Continuous
Uses breaks from color palette.
RasterAttributeTableFieldUsage
The RasterAttributeTableFieldUsage enum represents the usage of a Raster Attribute Table field.
@ RedMax
Field usage RedMax.
@ PixelCount
Field usage PixelCount.
@ AlphaMax
Field usage AlphaMax.
@ BlueMin
Field usage BlueMin.
@ Alpha
Field usage Alpha.
@ Generic
Field usage Generic.
@ GreenMax
Field usage GreenMax.
@ RedMin
Field usage RedMin.
@ MinMax
Field usage MinMax.
@ BlueMax
Field usage BlueMax.
@ AlphaMin
Field usage AlphaMin.
@ Green
Field usage Green.
@ MaxCount
Not used by QGIS: GDAL Maximum GFU value (equals to GFU_AlphaMax+1 currently).
@ GreenMin
Field usage GreenMin.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
Represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
int attributeCount() const
Returns the number of attributes attached to the feature.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
QColor color1() const
Returns the gradient start color.
QgsGradientColorRamp * clone() const override
Creates a clone of the color ramp.
QColor color2() const
Returns the gradient end color.
Represents a color stop within a QgsGradientColorRamp color ramp.
Renderer for paletted raster images.
static QgsPalettedRasterRenderer::MultiValueClassData rasterAttributeTableToClassData(const QgsRasterAttributeTable *attributeTable, int classificationColumn=-1, QgsColorRamp *ramp=nullptr)
Reads and returns classes from the Raster Attribute Table attributeTable, optionally classifying the ...
QList< QgsPalettedRasterRenderer::Class > ClassData
Map of value to class properties.
QList< QgsPalettedRasterRenderer::MultiValueClass > MultiValueClassData
Map of multi value to class properties.
The Field class represents a Raster Attribute Table field, including its name, usage and type.
Qgis::RasterAttributeTableFieldUsage usage
bool isRamp() const
Returns true if the field carries a color ramp component information (RedMin/RedMax,...
bool isColor() const
Returns true if the field carries a color component (Red, Green, Blue and optionally Alpha) informati...
Represents a Raster Attribute Table (RAT).
const QgsRasterAttributeTable::Field fieldByName(const QString name, bool *ok=nullptr) const
Returns a field by name or a default constructed field with empty name if the field is not found.
bool isDirty() const
Returns true if the Raster Attribute Table was modified from its last reading from the storage.
bool setColor(const int row, const QColor &color)
Sets the color for the row at rowIndex to color.
QList< QgsRasterAttributeTable::MinMaxClass > minMaxClasses(const int classificationColumn=-1) const
Returns the classes for a thematic Raster Attribute Table, classified by classificationColumn,...
QgsGradientColorRamp ramp(int row) const
Returns the gradient color ramp of the rat row or a default constructed gradient if row does not exis...
QgsRasterRenderer * createRenderer(QgsRasterDataProvider *provider, const int bandNumber, const int classificationColumn=-1)
Creates and returns a (possibly nullptr) raster renderer for the specified provider and bandNumber an...
bool readFromFile(const QString &path, QString *errorMessage=nullptr)
Reads the Raster Attribute Table from a DBF file specified by path, optionally reporting any error in...
QgsGradientColorRamp colorRamp(QStringList &labels, const int labelColumn=-1) const
Returns the color ramp for an athematic Raster Attribute Table setting the labels in labels,...
bool appendField(const QString &name, const Qgis::RasterAttributeTableFieldUsage usage, const QMetaType::Type type, QString *errorMessage=nullptr)
Creates a new field from name, usage and type and appends it to the fields, optionally reporting any ...
bool insertField(int position, const QgsRasterAttributeTable::Field &field, QString *errorMessage=nullptr)
Inserts a new field at position, optionally reporting any error in errorMessage, returns true on succ...
bool hasColor() const
Returns true if the Raster Attribute Table has color RGBA information.
bool setValue(const int row, const int column, const QVariant &value)
Sets the value for row and column.
static QList< Qgis::RasterAttributeTableFieldUsage > valueAndColorFieldUsages()
Returns the list of field usages for colors and values.
QList< QgsRasterAttributeTable::Field > fields() const
Returns the Raster Attribute Table fields.
static QgsRasterAttributeTable * createFromRaster(QgsRasterLayer *rasterLayer, int *bandNumber=nullptr)
Creates a new Raster Attribute Table from a raster layer, the renderer must be Paletted or SingleBand...
bool removeRow(int position=0, QString *errorMessage=nullptr)
Removes the row in the Raster Attribute Table at position, optionally reporting any error in errorMes...
bool appendRow(const QVariantList &data, QString *errorMessage=nullptr)
Appends a row of data to the RAT, optionally reporting any error in errorMessage, returns true on suc...
static QHash< Qgis::RasterAttributeTableFieldUsage, QgsRasterAttributeTable::UsageInformation > usageInformation()
Returns information about supported Raster Attribute Table usages.
Qgis::RasterAttributeTableType type() const
Returns the Raster Attribute Table type.
QList< Qgis::RasterAttributeTableFieldUsage > usages() const
Returns the list of field usages.
QVariantList row(const double matchValue) const
Returns a row of data for the given matchValue or and empty row if there is not match.
bool insertRow(int position, const QVariantList &rowData, QString *errorMessage=nullptr)
Inserts a row of rowData in the Raster Attribute Table at position, optionally reporting any error in...
bool writeToFile(const QString &path, QString *errorMessage=nullptr)
Writes the Raster Attribute Table to a DBF file specified by path, optionally reporting any error in ...
double minimumValue() const
Returns the minimum value of the MinMax (thematic) or Min (athematic) column, returns NaN on errors.
double maximumValue() const
Returns the maximum value of the MinMax (thematic) or Max (athematic) column, returns NaN on errors.
const QList< QgsRasterAttributeTable::Field > fieldsByUsage(const Qgis::RasterAttributeTableFieldUsage fieldUsage) const
Returns the list of fields matching fieldUsage.
void setDirty(bool isDirty)
Sets the Raster Attribute Table dirty state to isDirty;.
bool insertColor(int position, QString *errorMessage=nullptr)
Create RGBA fields and inserts them at position, optionally reporting any error in errorMessage,...
bool isValid(QString *errorMessage=nullptr) const
Returns true if the Raster Attribute Table is valid, optionally reporting validity checks results in ...
const QList< QList< QVariant > > data() const
Returns the Raster Attribute Table rows.
bool setRamp(const int row, const QColor &colorMin, const QColor &colorMax)
Sets the color ramp for the row at rowIndex to colorMin and colorMax.
PRIVATE QColor color(int row) const
Returns the color of the rat row or an invalid color if row does not exist or if there is no color de...
QList< QList< QVariant > > orderedRows() const
Returns the data rows ordered by the value column(s) in ascending order, if the attribute table type ...
static QString usageName(const Qgis::RasterAttributeTableFieldUsage fieldusage)
Returns the translated human readable name of fieldUsage.
bool hasRamp() const
Returns true if the Raster Attribute Table has ramp RGBA information.
QgsFeatureList qgisFeatures() const
Returns the Raster Attribute Table rows as a list of QgsFeature.
bool setFieldUsage(int fieldIndex, const Qgis::RasterAttributeTableFieldUsage usage)
Change the usage of the field at index fieldIndex to usage with checks for allowed types.
QString filePath() const
Returns the (possibly empty) path of the file-based RAT, the path is set when a RAT is read or writte...
bool insertRamp(int position, QString *errorMessage=nullptr)
Create RGBA minimum and maximum fields and inserts them at position, optionally reporting any error i...
QVariant value(const int row, const int column) const
Returns the value for row and column.
QgsFields qgisFields() const
Returns the Raster Attribute Table fields as QgsFields.
static Qgis::RasterAttributeTableFieldUsage guessFieldUsage(const QString &name, const QMetaType::Type type)
Try to determine the field usage from its name and type.
bool removeField(const QString &name, QString *errorMessage=nullptr)
Removes the field with name, optionally reporting any error in errorMessage, returns true on success.
Base class for raster data providers.
Represents a raster layer.
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
Raster renderer pipe that applies colors to a raster.
Interface for all raster shaders.
Raster renderer pipe for single band pseudocolor.
static QMetaType::Type variantTypeToMetaType(QVariant::Type variantType)
Converts a QVariant::Type to a QMetaType::Type.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
Options to pass to QgsVectorFileWriter::writeAsVectorFormat().
QString fileEncoding
Encoding to use.
QString driverName
OGR driver to use.
QStringList layerOptions
List of OGR layer creation options.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
@ CreateOrOverwriteFile
Create or overwrite file.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
QList< QgsFeature > QgsFeatureList
#define QgsDebugError(str)
Setting options for creating vector data providers.
Properties of a single value class.