Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[processing] Also add table output for raster unique values report al…
…gorithm

Allows values to be used within models
  • Loading branch information
nyalldawson committed Jun 4, 2018
1 parent e5e966b commit 3b2f690
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 3 deletions.
@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ raster_layer_unique_values.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy><gml:null>missing</gml:null></gml:boundedBy>

<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.0">
<ogr:value>826.00000000</ogr:value>
<ogr:count>4</ogr:count>
<ogr:m2>411.27572519</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.1">
<ogr:value>837.00000000</ogr:value>
<ogr:count>6</ogr:count>
<ogr:m2>616.91358779</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.2">
<ogr:value>843.00000000</ogr:value>
<ogr:count>6</ogr:count>
<ogr:m2>616.91358779</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.3">
<ogr:value>845.00000000</ogr:value>
<ogr:count>4</ogr:count>
<ogr:m2>411.27572519</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.4">
<ogr:value>851.00000000</ogr:value>
<ogr:count>9</ogr:count>
<ogr:m2>925.37038168</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.5">
<ogr:value>853.00000000</ogr:value>
<ogr:count>6</ogr:count>
<ogr:m2>616.91358779</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.6">
<ogr:value>859.00000000</ogr:value>
<ogr:count>10</ogr:count>
<ogr:m2>1028.18931298</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.7">
<ogr:value>861.00000000</ogr:value>
<ogr:count>4</ogr:count>
<ogr:m2>411.27572519</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.8">
<ogr:value>864.00000000</ogr:value>
<ogr:count>6</ogr:count>
<ogr:m2>616.91358779</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.9">
<ogr:value>866.00000000</ogr:value>
<ogr:count>9</ogr:count>
<ogr:m2>925.37038168</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.10">
<ogr:value>868.00000000</ogr:value>
<ogr:count>6</ogr:count>
<ogr:m2>616.91358779</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.11">
<ogr:value>872.00000000</ogr:value>
<ogr:count>4</ogr:count>
<ogr:m2>411.27572519</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.12">
<ogr:value>873.00000000</ogr:value>
<ogr:count>9</ogr:count>
<ogr:m2>925.37038168</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.13">
<ogr:value>878.00000000</ogr:value>
<ogr:count>6</ogr:count>
<ogr:m2>616.91358779</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.14">
<ogr:value>880.00000000</ogr:value>
<ogr:count>6</ogr:count>
<ogr:m2>616.91358779</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.15">
<ogr:value>881.00000000</ogr:value>
<ogr:count>6</ogr:count>
<ogr:m2>616.91358779</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.16">
<ogr:value>890.00000000</ogr:value>
<ogr:count>13</ogr:count>
<ogr:m2>1336.64610687</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:raster_layer_unique_values fid="raster_layer_unique_values.17">
<ogr:value>899.00000000</ogr:value>
<ogr:count>6</ogr:count>
<ogr:m2>616.91358779</ogr:m2>
</ogr:raster_layer_unique_values>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="raster_layer_unique_values" type="ogr:raster_layer_unique_values_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="raster_layer_unique_values_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="value" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:totalDigits value="21"/>
<xs:fractionDigits value="8"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="count" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="m2" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:totalDigits value="21"/>
<xs:fractionDigits value="8"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
16 changes: 16 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -3973,6 +3973,22 @@ tests:
- '890</td><td>13</td><td>1336.646106872878'
- '899</td><td>6</td><td>616.9135877874822'

- algorithm: native:rasterlayeruniquevaluesreport
name: Raster layer unique values report (table)
params:
BAND: 1
INPUT:
name: raster.tif
type: raster
results:
OUTPUT_TABLE:
name: expected/raster_layer_unique_values.gml
type: vector
compare:
fields:
__all__:
precision: 2

- algorithm: qgis:pointsdisplacement
name: Point displacement
params:
Expand Down
36 changes: 33 additions & 3 deletions src/analysis/processing/qgsalgorithmrasterlayeruniquevalues.cpp
Expand Up @@ -53,6 +53,8 @@ void QgsRasterLayerUniqueValuesReportAlgorithm::initAlgorithm( const QVariantMap
QObject::tr( "Band number" ), 1, QStringLiteral( "INPUT" ) ) );
addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT_HTML_FILE" ),
QObject::tr( "Unique values report" ), QObject::tr( "HTML files (*.html)" ), QVariant(), true ) );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT_TABLE" ),
QObject::tr( "Unique values table" ), QgsProcessing::TypeVector, QVariant(), true, false ) );

addOutput( new QgsProcessingOutputString( QStringLiteral( "EXTENT" ), QObject::tr( "Extent" ) ) );
addOutput( new QgsProcessingOutputString( QStringLiteral( "CRS_AUTHID" ), QObject::tr( "CRS authority identifier" ) ) );
Expand Down Expand Up @@ -98,6 +100,21 @@ QVariantMap QgsRasterLayerUniqueValuesReportAlgorithm::processAlgorithm( const Q
int band = parameterAsInt( parameters, QStringLiteral( "BAND" ), context );
QString outputFile = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT_HTML_FILE" ), context );

QString areaUnit = QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::distanceToAreaUnit( mCrs.mapUnits() ) );

QString tableDest;
std::unique_ptr< QgsFeatureSink > sink;
if ( parameters.contains( QStringLiteral( "OUTPUT_TABLE" ) ) && parameters.value( QStringLiteral( "OUTPUT_TABLE" ) ).isValid() )
{
QgsFields outFields;
outFields.append( QgsField( QStringLiteral( "value" ), QVariant::Double, QString(), 20, 8 ) );
outFields.append( QgsField( QStringLiteral( "count" ), QVariant::Int, QString(), 20 ) );
outFields.append( QgsField( areaUnit.replace( QStringLiteral( "²" ), QStringLiteral( "2" ) ), QVariant::Double, QString(), 20, 8 ) );
sink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT_TABLE" ), context, tableDest, outFields, QgsWkbTypes::NoGeometry, QgsCoordinateReferenceSystem() ) );
if ( !sink )
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT_TABLE" ) ) );
}

QHash< double, qgssize > uniqueValues;
qgssize noDataCount = 0;

Expand Down Expand Up @@ -155,13 +172,14 @@ QVariantMap QgsRasterLayerUniqueValuesReportAlgorithm::processAlgorithm( const Q
outputs.insert( QStringLiteral( "TOTAL_PIXEL_COUNT" ), layerSize );
outputs.insert( QStringLiteral( "NODATA_PIXEL_COUNT" ), noDataCount );

double pixelArea = mRasterUnitsPerPixelX * mRasterUnitsPerPixelY;

if ( !outputFile.isEmpty() )
{
QFile file( outputFile );
if ( file.open( QIODevice::WriteOnly | QIODevice::Text ) )
{
const QString areaUnit = QgsStringUtils::ampersandEncode( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::distanceToAreaUnit( mCrs.mapUnits() ) ) );
double pixelArea = mRasterUnitsPerPixelX * mRasterUnitsPerPixelY;
const QString encodedAreaUnit = QgsStringUtils::ampersandEncode( areaUnit );

QTextStream out( &file );
out << QStringLiteral( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
Expand All @@ -173,7 +191,7 @@ QVariantMap QgsRasterLayerUniqueValuesReportAlgorithm::processAlgorithm( const Q
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "Total pixel count" ) ).arg( layerSize );
if ( mHasNoDataValue )
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "NODATA pixel count" ) ).arg( noDataCount );
out << QStringLiteral( "<table><tr><td>%1</td><td>%2</td><td>%3 (%4)</td></tr>\n" ).arg( QObject::tr( "Value" ), QObject::tr( "Pixel count" ), QObject::tr( "Area" ), areaUnit );
out << QStringLiteral( "<table><tr><td>%1</td><td>%2</td><td>%3 (%4)</td></tr>\n" ).arg( QObject::tr( "Value" ), QObject::tr( "Pixel count" ), QObject::tr( "Area" ), encodedAreaUnit );

for ( auto it = sortedUniqueValues.constBegin(); it != sortedUniqueValues.constEnd(); ++it )
{
Expand All @@ -185,6 +203,18 @@ QVariantMap QgsRasterLayerUniqueValuesReportAlgorithm::processAlgorithm( const Q
}
}

if ( sink )
{
for ( auto it = sortedUniqueValues.constBegin(); it != sortedUniqueValues.constEnd(); ++it )
{
QgsFeature f;
double area = it.value() * pixelArea;
f.setAttributes( QgsAttributes() << it.key() << it.value() << area );
sink->addFeature( f, QgsFeatureSink::FastInsert );
}
outputs.insert( QStringLiteral( "OUTPUT_TABLE" ), tableDest );
}

return outputs;
}

Expand Down

0 comments on commit 3b2f690

Please sign in to comment.