mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
[needs-docs][processing] Port SAGA raster surface volume to native QGIS alg
The SAGA version of this algorithm is of limited use in QGIS, because the volume calculated is embedded only in the SAGA terminal output. This prevents it being saved to a file, or reused within a model as an input to a later model step. It's also very user-unfriendly, because users must know to manually scan the algorithm log to find the SAGA output. Given that the maths here is trivial, this commit ports the algorithm across to be a native QGIS c++ algorithm. The algorithm duplicates the SAGA alg 1:1, but outputs the volume (and area) to either a HTML report, or a vector table. Additionally, the outputs are exported as numeric outputs from the algorithm, allowing them to be re-used within models. (It's also considerably faster, because it avoids the forced conversion to SAGA raster format) Fixes #8607 (properly, even though that report is closed)
This commit is contained in:
parent
e3fda18aca
commit
195d98f43a
BIN
python/plugins/processing/tests/testdata/custom/dem_crs.tif
vendored
Normal file
BIN
python/plugins/processing/tests/testdata/custom/dem_crs.tif
vendored
Normal file
Binary file not shown.
16
python/plugins/processing/tests/testdata/expected/surface_vol_above.gml
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/surface_vol_above.gml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ surface_vol_above.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:surface_vol_above fid="surface_vol_above.0">
|
||||
<ogr:volume>0.06480527</ogr:volume>
|
||||
<ogr:deg2>0.00095901</ogr:deg2>
|
||||
<ogr:pixel_count>95901</ogr:pixel_count>
|
||||
</ogr:surface_vol_above>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
6
python/plugins/processing/tests/testdata/expected/surface_vol_above.html
vendored
Normal file
6
python/plugins/processing/tests/testdata/expected/surface_vol_above.html
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
|
||||
<p>Analyzed file: /home/nyall/dev/QGIS/python/plugins/processing/tests/testdata/dem.tif (band 1)</p>
|
||||
<p>Volume: 0.0648052733680633</p>
|
||||
<p>Pixel count: 95901</p>
|
||||
<p>Area: 0.0009590099999998638 deg2</p>
|
||||
</body></html>
|
45
python/plugins/processing/tests/testdata/expected/surface_vol_above.xsd
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/surface_vol_above.xsd
vendored
Normal file
@ -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="surface_vol_above" type="ogr:surface_vol_above_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="surface_vol_above_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="volume" 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="deg2" 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="pixel_count" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:long">
|
||||
<xs:totalDigits value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
16
python/plugins/processing/tests/testdata/expected/surface_vol_above_crs.gml
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/surface_vol_above_crs.gml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ surface_vol_above_crs.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:surface_vol_above_crs fid="surface_vol_above_crs.0">
|
||||
<ogr:volume>413784918.00990051</ogr:volume>
|
||||
<ogr:m2>11497732.58555590</ogr:m2>
|
||||
<ogr:pixel_count>64692</ogr:pixel_count>
|
||||
</ogr:surface_vol_above_crs>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
6
python/plugins/processing/tests/testdata/expected/surface_vol_above_crs.html
vendored
Normal file
6
python/plugins/processing/tests/testdata/expected/surface_vol_above_crs.html
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
|
||||
<p>Analyzed file: /home/nyall/dev/QGIS/python/plugins/processing/tests/testdata/custom/dem_crs.tif (band 1)</p>
|
||||
<p>Volume: 413784918.0099005</p>
|
||||
<p>Pixel count: 64692</p>
|
||||
<p>Area: 11497732.5855559 m2</p>
|
||||
</body></html>
|
45
python/plugins/processing/tests/testdata/expected/surface_vol_above_crs.xsd
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/surface_vol_above_crs.xsd
vendored
Normal file
@ -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="surface_vol_above_crs" type="ogr:surface_vol_above_crs_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="surface_vol_above_crs_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="volume" 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="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:element name="pixel_count" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:long">
|
||||
<xs:totalDigits value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
16
python/plugins/processing/tests/testdata/expected/surface_vol_add.gml
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/surface_vol_add.gml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ surface_vol_add.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:surface_vol_add fid="surface_vol_add.0">
|
||||
<ogr:volume>0.06802753</ogr:volume>
|
||||
<ogr:deg2>0.00130550</ogr:deg2>
|
||||
<ogr:pixel_count>130550</ogr:pixel_count>
|
||||
</ogr:surface_vol_add>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
6
python/plugins/processing/tests/testdata/expected/surface_vol_add.html
vendored
Normal file
6
python/plugins/processing/tests/testdata/expected/surface_vol_add.html
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
|
||||
<p>Analyzed file: /home/nyall/dev/QGIS/python/plugins/processing/tests/testdata/dem.tif (band 1)</p>
|
||||
<p>Volume: 0.06802752691184032</p>
|
||||
<p>Pixel count: 130550</p>
|
||||
<p>Area: 0.001305499999999814 deg2</p>
|
||||
</body></html>
|
45
python/plugins/processing/tests/testdata/expected/surface_vol_add.xsd
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/surface_vol_add.xsd
vendored
Normal file
@ -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="surface_vol_add" type="ogr:surface_vol_add_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="surface_vol_add_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="volume" 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="deg2" 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="pixel_count" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:long">
|
||||
<xs:totalDigits value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
16
python/plugins/processing/tests/testdata/expected/surface_vol_add_crs.gml
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/surface_vol_add_crs.gml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ surface_vol_add_crs.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:surface_vol_add_crs fid="surface_vol_add_crs.0">
|
||||
<ogr:volume>893436802.88886535</ogr:volume>
|
||||
<ogr:m2>23202698.77333090</ogr:m2>
|
||||
<ogr:pixel_count>130550</ogr:pixel_count>
|
||||
</ogr:surface_vol_add_crs>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
6
python/plugins/processing/tests/testdata/expected/surface_vol_add_crs.html
vendored
Normal file
6
python/plugins/processing/tests/testdata/expected/surface_vol_add_crs.html
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
|
||||
<p>Analyzed file: /home/nyall/dev/QGIS/python/plugins/processing/tests/testdata/custom/dem_crs.tif (band 1)</p>
|
||||
<p>Volume: 893436802.8888654</p>
|
||||
<p>Pixel count: 130550</p>
|
||||
<p>Area: 23202698.7733309 m2</p>
|
||||
</body></html>
|
45
python/plugins/processing/tests/testdata/expected/surface_vol_add_crs.xsd
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/surface_vol_add_crs.xsd
vendored
Normal file
@ -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="surface_vol_add_crs" type="ogr:surface_vol_add_crs_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="surface_vol_add_crs_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="volume" 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="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:element name="pixel_count" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:long">
|
||||
<xs:totalDigits value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
16
python/plugins/processing/tests/testdata/expected/surface_vol_below.gml
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/surface_vol_below.gml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ surface_vol_below.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:surface_vol_below fid="surface_vol_below.0">
|
||||
<ogr:volume>-0.00322225</ogr:volume>
|
||||
<ogr:deg2>0.00034600</ogr:deg2>
|
||||
<ogr:pixel_count>34600</ogr:pixel_count>
|
||||
</ogr:surface_vol_below>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
6
python/plugins/processing/tests/testdata/expected/surface_vol_below.html
vendored
Normal file
6
python/plugins/processing/tests/testdata/expected/surface_vol_below.html
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
|
||||
<p>Analyzed file: /home/nyall/dev/QGIS/python/plugins/processing/tests/testdata/dem.tif (band 1)</p>
|
||||
<p>Volume: -0.003222253543777008</p>
|
||||
<p>Pixel count: 34600</p>
|
||||
<p>Area: 0.0003459999999999508 deg2</p>
|
||||
</body></html>
|
45
python/plugins/processing/tests/testdata/expected/surface_vol_below.xsd
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/surface_vol_below.xsd
vendored
Normal file
@ -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="surface_vol_below" type="ogr:surface_vol_below_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="surface_vol_below_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="volume" 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="deg2" 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="pixel_count" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:long">
|
||||
<xs:totalDigits value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
16
python/plugins/processing/tests/testdata/expected/surface_vol_below_crs.gml
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/surface_vol_below_crs.gml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ surface_vol_below_crs.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:surface_vol_below_crs fid="surface_vol_below_crs.0">
|
||||
<ogr:volume>-479651884.87896484</ogr:volume>
|
||||
<ogr:m2>11669775.57607742</ogr:m2>
|
||||
<ogr:pixel_count>65660</ogr:pixel_count>
|
||||
</ogr:surface_vol_below_crs>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
6
python/plugins/processing/tests/testdata/expected/surface_vol_below_crs.html
vendored
Normal file
6
python/plugins/processing/tests/testdata/expected/surface_vol_below_crs.html
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
|
||||
<p>Analyzed file: /home/nyall/dev/QGIS/python/plugins/processing/tests/testdata/custom/dem_crs.tif (band 1)</p>
|
||||
<p>Volume: -479651884.8789648</p>
|
||||
<p>Pixel count: 65660</p>
|
||||
<p>Area: 11669775.57607742 m2</p>
|
||||
</body></html>
|
45
python/plugins/processing/tests/testdata/expected/surface_vol_below_crs.xsd
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/surface_vol_below_crs.xsd
vendored
Normal file
@ -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="surface_vol_below_crs" type="ogr:surface_vol_below_crs_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="surface_vol_below_crs_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="volume" 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="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:element name="pixel_count" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:long">
|
||||
<xs:totalDigits value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
16
python/plugins/processing/tests/testdata/expected/surface_vol_gaps.gml
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/surface_vol_gaps.gml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ surface_vol_gaps.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:surface_vol_gaps fid="surface_vol_gaps.0">
|
||||
<ogr:volume>0.06382041</ogr:volume>
|
||||
<ogr:deg2>0.00094259</ogr:deg2>
|
||||
<ogr:pixel_count>94259</ogr:pixel_count>
|
||||
</ogr:surface_vol_gaps>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
45
python/plugins/processing/tests/testdata/expected/surface_vol_gaps.xsd
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/surface_vol_gaps.xsd
vendored
Normal file
@ -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="surface_vol_gaps" type="ogr:surface_vol_gaps_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="surface_vol_gaps_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="volume" 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="deg2" 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="pixel_count" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:long">
|
||||
<xs:totalDigits value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
16
python/plugins/processing/tests/testdata/expected/surface_vol_subtract.gml
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/surface_vol_subtract.gml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ surface_vol_subtract.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:surface_vol_subtract fid="surface_vol_subtract.0">
|
||||
<ogr:volume>0.06158302</ogr:volume>
|
||||
<ogr:deg2>0.00130550</ogr:deg2>
|
||||
<ogr:pixel_count>130550</ogr:pixel_count>
|
||||
</ogr:surface_vol_subtract>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
6
python/plugins/processing/tests/testdata/expected/surface_vol_subtract.html
vendored
Normal file
6
python/plugins/processing/tests/testdata/expected/surface_vol_subtract.html
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
|
||||
<p>Analyzed file: /home/nyall/dev/QGIS/python/plugins/processing/tests/testdata/dem.tif (band 1)</p>
|
||||
<p>Volume: 0.06158301982428629</p>
|
||||
<p>Pixel count: 130550</p>
|
||||
<p>Area: 0.001305499999999814 deg2</p>
|
||||
</body></html>
|
45
python/plugins/processing/tests/testdata/expected/surface_vol_subtract.xsd
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/surface_vol_subtract.xsd
vendored
Normal file
@ -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="surface_vol_subtract" type="ogr:surface_vol_subtract_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="surface_vol_subtract_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="volume" 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="deg2" 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="pixel_count" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:long">
|
||||
<xs:totalDigits value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
16
python/plugins/processing/tests/testdata/expected/surface_vol_subtract_crs.gml
vendored
Normal file
16
python/plugins/processing/tests/testdata/expected/surface_vol_subtract_crs.gml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ surface_vol_subtract_crs.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:surface_vol_subtract_crs fid="surface_vol_subtract_crs.0">
|
||||
<ogr:volume>-65866966.86906432</ogr:volume>
|
||||
<ogr:m2>23202698.77333090</ogr:m2>
|
||||
<ogr:pixel_count>130550</ogr:pixel_count>
|
||||
</ogr:surface_vol_subtract_crs>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
6
python/plugins/processing/tests/testdata/expected/surface_vol_subtract_crs.html
vendored
Normal file
6
python/plugins/processing/tests/testdata/expected/surface_vol_subtract_crs.html
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/></head><body>
|
||||
<p>Analyzed file: /home/nyall/dev/QGIS/python/plugins/processing/tests/testdata/custom/dem_crs.tif (band 1)</p>
|
||||
<p>Volume: -65866966.86906432</p>
|
||||
<p>Pixel count: 130550</p>
|
||||
<p>Area: 23202698.7733309 m2</p>
|
||||
</body></html>
|
45
python/plugins/processing/tests/testdata/expected/surface_vol_subtract_crs.xsd
vendored
Normal file
45
python/plugins/processing/tests/testdata/expected/surface_vol_subtract_crs.xsd
vendored
Normal file
@ -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="surface_vol_subtract_crs" type="ogr:surface_vol_subtract_crs_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="surface_vol_subtract_crs_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="volume" 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="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:element name="pixel_count" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:long">
|
||||
<xs:totalDigits value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
@ -6793,4 +6793,186 @@ tests:
|
||||
pk:
|
||||
- pk
|
||||
|
||||
- algorithm: native:rastersurfacevolume
|
||||
name: Surface volume above
|
||||
params:
|
||||
BAND: 1
|
||||
INPUT:
|
||||
name: dem.tif
|
||||
type: raster
|
||||
LEVEL: 100.0
|
||||
METHOD: 0
|
||||
results:
|
||||
OUTPUT_HTML_FILE:
|
||||
name: expected/surface_vol_above.html
|
||||
type: regex
|
||||
rules:
|
||||
- 'Volume: 0.064805'
|
||||
- 'Pixel count: 95901'
|
||||
- 'Area: 0.000959'
|
||||
OUTPUT_TABLE:
|
||||
name: expected/surface_vol_above.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:rastersurfacevolume
|
||||
name: Surface volume Below
|
||||
params:
|
||||
BAND: 1
|
||||
INPUT:
|
||||
name: dem.tif
|
||||
type: raster
|
||||
LEVEL: 100.0
|
||||
METHOD: 1
|
||||
results:
|
||||
OUTPUT_HTML_FILE:
|
||||
name: expected/surface_vol_below.html
|
||||
type: regex
|
||||
rules:
|
||||
- 'Volume: -0.00322225'
|
||||
- 'Pixel count: 34600'
|
||||
- 'Area: 0.00034599'
|
||||
OUTPUT_TABLE:
|
||||
name: expected/surface_vol_below.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:rastersurfacevolume
|
||||
name: Surface volume subtract below
|
||||
params:
|
||||
BAND: 1
|
||||
INPUT:
|
||||
name: dem.tif
|
||||
type: raster
|
||||
LEVEL: 100.0
|
||||
METHOD: 2
|
||||
results:
|
||||
OUTPUT_HTML_FILE:
|
||||
name: expected/surface_vol_subtract.html
|
||||
type: regex
|
||||
rules:
|
||||
- 'Volume: 0.0615830'
|
||||
- 'Pixel count: 130550'
|
||||
- 'Area: 0.00130549'
|
||||
OUTPUT_TABLE:
|
||||
name: expected/surface_vol_subtract.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:rastersurfacevolume
|
||||
name: Surface volume add below
|
||||
params:
|
||||
BAND: 1
|
||||
INPUT:
|
||||
name: dem.tif
|
||||
type: raster
|
||||
LEVEL: 100.0
|
||||
METHOD: 3
|
||||
results:
|
||||
OUTPUT_HTML_FILE:
|
||||
name: expected/surface_vol_add.html
|
||||
type: regex
|
||||
rules:
|
||||
- 'Volume: 0.06802752'
|
||||
- 'Pixel count: 130550'
|
||||
- 'Area: 0.00130549'
|
||||
OUTPUT_TABLE:
|
||||
name: expected/surface_vol_add.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:rastersurfacevolume
|
||||
name: Surface volume above (meters)
|
||||
params:
|
||||
BAND: 1
|
||||
INPUT:
|
||||
name: custom/dem_crs.tif
|
||||
type: raster
|
||||
LEVEL: 150.0
|
||||
METHOD: 0
|
||||
results:
|
||||
OUTPUT_HTML_FILE:
|
||||
name: expected/surface_vol_above_crs.html
|
||||
type: regex
|
||||
rules:
|
||||
- 'Volume: 413784918\.'
|
||||
- 'Pixel count: 64692'
|
||||
- 'Area: 11497732\.'
|
||||
OUTPUT_TABLE:
|
||||
name: expected/surface_vol_above_crs.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:rastersurfacevolume
|
||||
name: Surface volume below (meters)
|
||||
params:
|
||||
BAND: 1
|
||||
INPUT:
|
||||
name: custom/dem_crs.tif
|
||||
type: raster
|
||||
LEVEL: 150.0
|
||||
METHOD: 1
|
||||
results:
|
||||
OUTPUT_HTML_FILE:
|
||||
name: expected/surface_vol_below_crs.html
|
||||
type: regex
|
||||
rules:
|
||||
- 'Volume: -479651884\.'
|
||||
- 'Pixel count: 65660'
|
||||
- 'Area: 11669775\.'
|
||||
OUTPUT_TABLE:
|
||||
name: expected/surface_vol_below_crs.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:rastersurfacevolume
|
||||
name: Surface volume subtract below (meters)
|
||||
params:
|
||||
BAND: 1
|
||||
INPUT:
|
||||
name: custom/dem_crs.tif
|
||||
type: raster
|
||||
LEVEL: 150.0
|
||||
METHOD: 2
|
||||
results:
|
||||
OUTPUT_HTML_FILE:
|
||||
name: expected/surface_vol_subtract_crs.html
|
||||
type: regex
|
||||
rules:
|
||||
- 'Volume: -65866966\.'
|
||||
- 'Pixel count: 130550'
|
||||
- 'Area: 23202698\.'
|
||||
OUTPUT_TABLE:
|
||||
name: expected/surface_vol_subtract_crs.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:rastersurfacevolume
|
||||
name: Surface volume add below (meters)
|
||||
params:
|
||||
BAND: 1
|
||||
INPUT:
|
||||
name: custom/dem_crs.tif
|
||||
type: raster
|
||||
LEVEL: 150.0
|
||||
METHOD: 3
|
||||
results:
|
||||
OUTPUT_HTML_FILE:
|
||||
name: expected/surface_vol_add_crs.html
|
||||
type: regex
|
||||
rules:
|
||||
- 'Volume: 893436802\.'
|
||||
- 'Pixel count: 130550'
|
||||
- 'Area: 23202698\.'
|
||||
OUTPUT_TABLE:
|
||||
name: expected/surface_vol_add_crs.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:rastersurfacevolume
|
||||
name: Surface volume with gaps
|
||||
params:
|
||||
BAND: 1
|
||||
INPUT:
|
||||
name: custom/dem_gaps.tif
|
||||
type: raster
|
||||
LEVEL: 101.0
|
||||
METHOD: 0
|
||||
results:
|
||||
OUTPUT_TABLE:
|
||||
name: expected/surface_vol_gaps.gml
|
||||
type: vector
|
||||
|
||||
# See ../README.md for a description of the file format
|
||||
|
@ -77,6 +77,7 @@ SET(QGIS_ANALYSIS_SRCS
|
||||
processing/qgsalgorithmprojectpointcartesian.cpp
|
||||
processing/qgsalgorithmpromotetomultipart.cpp
|
||||
processing/qgsalgorithmrasterlayeruniquevalues.cpp
|
||||
processing/qgsalgorithmrastersurfacevolume.cpp
|
||||
processing/qgsalgorithmrasterzonalstats.cpp
|
||||
processing/qgsalgorithmreclassifybylayer.cpp
|
||||
processing/qgsalgorithmremoveduplicatesbyattribute.cpp
|
||||
|
250
src/analysis/processing/qgsalgorithmrastersurfacevolume.cpp
Normal file
250
src/analysis/processing/qgsalgorithmrastersurfacevolume.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
/***************************************************************************
|
||||
qgsalgorithmrasterlayeruniquevalues.cpp
|
||||
---------------------
|
||||
begin : January 2019
|
||||
copyright : (C) 2019 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsalgorithmrastersurfacevolume.h"
|
||||
#include "qgsstringutils.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
QString QgsRasterSurfaceVolumeAlgorithm::name() const
|
||||
{
|
||||
return QStringLiteral( "rastersurfacevolume" );
|
||||
}
|
||||
|
||||
QString QgsRasterSurfaceVolumeAlgorithm::displayName() const
|
||||
{
|
||||
return QObject::tr( "Raster surface volume" );
|
||||
}
|
||||
|
||||
QStringList QgsRasterSurfaceVolumeAlgorithm::tags() const
|
||||
{
|
||||
return QObject::tr( "sum,volume,area,height,terrain,dem,elevation" ).split( ',' );
|
||||
}
|
||||
|
||||
QString QgsRasterSurfaceVolumeAlgorithm::group() const
|
||||
{
|
||||
return QObject::tr( "Raster analysis" );
|
||||
}
|
||||
|
||||
QString QgsRasterSurfaceVolumeAlgorithm::groupId() const
|
||||
{
|
||||
return QStringLiteral( "rasteranalysis" );
|
||||
}
|
||||
|
||||
void QgsRasterSurfaceVolumeAlgorithm::initAlgorithm( const QVariantMap & )
|
||||
{
|
||||
addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "INPUT" ),
|
||||
QObject::tr( "Input layer" ) ) );
|
||||
addParameter( new QgsProcessingParameterBand( QStringLiteral( "BAND" ),
|
||||
QObject::tr( "Band number" ), 1, QStringLiteral( "INPUT" ) ) );
|
||||
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "LEVEL" ),
|
||||
QObject::tr( "Base level" ), QgsProcessingParameterNumber::Double, 0 ) );
|
||||
addParameter( new QgsProcessingParameterEnum( QStringLiteral( "METHOD" ),
|
||||
QObject::tr( "Method" ), QStringList()
|
||||
<< QObject::tr( "Count Only Above Base Level" )
|
||||
<< QObject::tr( "Count Only Below Base Level" )
|
||||
<< QObject::tr( "Subtract Volumes Below Base Level" )
|
||||
<< QObject::tr( "Add Volumes Below Base Level" ) ) );
|
||||
|
||||
addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT_HTML_FILE" ),
|
||||
QObject::tr( "Surface volume report" ), QObject::tr( "HTML files (*.html)" ), QVariant(), true ) );
|
||||
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT_TABLE" ),
|
||||
QObject::tr( "Surface volume table" ), QgsProcessing::TypeVector, QVariant(), true, false ) );
|
||||
|
||||
addOutput( new QgsProcessingOutputNumber( QStringLiteral( "VOLUME" ), QObject::tr( "Volume" ) ) );
|
||||
addOutput( new QgsProcessingOutputNumber( QStringLiteral( "PIXEL_COUNT" ), QObject::tr( "Pixel count" ) ) );
|
||||
addOutput( new QgsProcessingOutputNumber( QStringLiteral( "AREA" ), QObject::tr( "Area" ) ) );
|
||||
}
|
||||
|
||||
QString QgsRasterSurfaceVolumeAlgorithm::shortHelpString() const
|
||||
{
|
||||
return QObject::tr( "This algorithm calculates the volume under a raster grid's surface.\n\n"
|
||||
"Several methods of volume calculation are available, which control whether "
|
||||
"only values above or below the specified base level are considered, or "
|
||||
"whether volumes below the base level should be added or subtracted from the total volume.\n\n"
|
||||
"The algorithm outputs the calculated volume, the total area, and the total number of pixels analysed. "
|
||||
"If the 'Count Only Above Base Level' or 'Count Only Below Base Level' methods are used, "
|
||||
"then the calculated area and pixel count only includes pixels which are above or below the "
|
||||
"specified base level respectively.\n\n"
|
||||
"Units of the calculated volume are dependent on the coordinate reference system of "
|
||||
"the input raster file. For a CRS in meters, with a DEM height in meters, the calculated "
|
||||
"value will be in meters³. If instead the input raster is in a geographic coordinate system "
|
||||
"(e.g. latitude/longitude values), then the result will be in degrees² × meters, and an "
|
||||
"appropriate scaling factor will need to be applied in order to convert to meters³." );
|
||||
}
|
||||
|
||||
QString QgsRasterSurfaceVolumeAlgorithm::shortDescription() const
|
||||
{
|
||||
return QObject::tr( "Calculates the volume under a raster grid's surface." );
|
||||
}
|
||||
|
||||
QgsRasterSurfaceVolumeAlgorithm *QgsRasterSurfaceVolumeAlgorithm::createInstance() const
|
||||
{
|
||||
return new QgsRasterSurfaceVolumeAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsRasterSurfaceVolumeAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
{
|
||||
QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT" ), context );
|
||||
int band = parameterAsInt( parameters, QStringLiteral( "BAND" ), context );
|
||||
|
||||
if ( !layer )
|
||||
throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "INPUT" ) ) );
|
||||
|
||||
mBand = parameterAsInt( parameters, QStringLiteral( "BAND" ), context );
|
||||
if ( mBand < 1 || mBand > layer->bandCount() )
|
||||
throw QgsProcessingException( QObject::tr( "Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand )
|
||||
.arg( layer->bandCount() ) );
|
||||
|
||||
mInterface.reset( layer->dataProvider()->clone() );
|
||||
mHasNoDataValue = layer->dataProvider()->sourceHasNoDataValue( band );
|
||||
mLayerWidth = layer->width();
|
||||
mLayerHeight = layer->height();
|
||||
mExtent = layer->extent();
|
||||
mCrs = layer->crs();
|
||||
mRasterUnitsPerPixelX = layer->rasterUnitsPerPixelX();
|
||||
mRasterUnitsPerPixelY = layer->rasterUnitsPerPixelY();
|
||||
mSource = layer->source();
|
||||
|
||||
mLevel = parameterAsDouble( parameters, QStringLiteral( "LEVEL" ), context );
|
||||
mMethod = static_cast< Method >( parameterAsEnum( parameters, QStringLiteral( "METHOD" ), context ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsRasterSurfaceVolumeAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
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( "volume" ), QVariant::Double, QString(), 20, 8 ) );
|
||||
outFields.append( QgsField( areaUnit.replace( QStringLiteral( "²" ), QStringLiteral( "2" ) ), QVariant::Double, QString(), 20, 8 ) );
|
||||
outFields.append( QgsField( QStringLiteral( "pixel_count" ), QVariant::LongLong ) );
|
||||
sink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT_TABLE" ), context, tableDest, outFields, QgsWkbTypes::NoGeometry, QgsCoordinateReferenceSystem() ) );
|
||||
if ( !sink )
|
||||
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT_TABLE" ) ) );
|
||||
}
|
||||
|
||||
double volume = 0;
|
||||
long long count = 0;
|
||||
|
||||
int maxWidth = QgsRasterIterator::DEFAULT_MAXIMUM_TILE_WIDTH;
|
||||
int maxHeight = QgsRasterIterator::DEFAULT_MAXIMUM_TILE_HEIGHT;
|
||||
int nbBlocksWidth = static_cast< int >( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
|
||||
int nbBlocksHeight = static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
|
||||
int nbBlocks = nbBlocksWidth * nbBlocksHeight;
|
||||
|
||||
QgsRasterIterator iter( mInterface.get() );
|
||||
iter.startRasterRead( mBand, mLayerWidth, mLayerHeight, mExtent );
|
||||
|
||||
int iterLeft = 0;
|
||||
int iterTop = 0;
|
||||
int iterCols = 0;
|
||||
int iterRows = 0;
|
||||
std::unique_ptr< QgsRasterBlock > rasterBlock;
|
||||
while ( iter.readNextRasterPart( mBand, iterCols, iterRows, rasterBlock, iterLeft, iterTop ) )
|
||||
{
|
||||
feedback->setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
|
||||
for ( int row = 0; row < iterRows; row++ )
|
||||
{
|
||||
if ( feedback->isCanceled() )
|
||||
break;
|
||||
for ( int column = 0; column < iterCols; column++ )
|
||||
{
|
||||
if ( mHasNoDataValue && rasterBlock->isNoData( row, column ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const double z = rasterBlock->value( row, column ) - mLevel;
|
||||
|
||||
switch ( mMethod )
|
||||
{
|
||||
case CountOnlyAboveBaseLevel:
|
||||
if ( z > 0.0 )
|
||||
{
|
||||
volume += z;
|
||||
count++;
|
||||
}
|
||||
continue;
|
||||
|
||||
case CountOnlyBelowBaseLevel:
|
||||
if ( z < 0.0 )
|
||||
{
|
||||
volume += z;
|
||||
count++;
|
||||
}
|
||||
continue;
|
||||
|
||||
case SubtractVolumesBelowBaseLevel:
|
||||
volume += z;
|
||||
count++;
|
||||
continue;
|
||||
|
||||
case AddVolumesBelowBaseLevel:
|
||||
volume += std::fabs( z );
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap outputs;
|
||||
double pixelArea = mRasterUnitsPerPixelX * mRasterUnitsPerPixelY;
|
||||
double area = count * pixelArea;
|
||||
volume *= pixelArea;
|
||||
if ( !outputFile.isEmpty() )
|
||||
{
|
||||
QFile file( outputFile );
|
||||
if ( file.open( QIODevice::WriteOnly | QIODevice::Text ) )
|
||||
{
|
||||
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" );
|
||||
out << QStringLiteral( "<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( "Analyzed file" ), mSource, QObject::tr( "band" ) ).arg( mBand );
|
||||
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "Volume" ), QString::number( volume, 'g', 16 ) );
|
||||
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "Pixel count" ) ).arg( count );
|
||||
out << QObject::tr( "<p>%1: %2 %3</p>\n" ).arg( QObject::tr( "Area" ), QString::number( area, 'g', 16 ), encodedAreaUnit );
|
||||
out << QStringLiteral( "</body></html>" );
|
||||
outputs.insert( QStringLiteral( "OUTPUT_HTML_FILE" ), outputFile );
|
||||
}
|
||||
}
|
||||
|
||||
if ( sink )
|
||||
{
|
||||
QgsFeature f;
|
||||
f.setAttributes( QgsAttributes() << volume << area << count );
|
||||
sink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
outputs.insert( QStringLiteral( "OUTPUT_TABLE" ), tableDest );
|
||||
}
|
||||
outputs.insert( QStringLiteral( "VOLUME" ), volume );
|
||||
outputs.insert( QStringLiteral( "AREA" ), area );
|
||||
outputs.insert( QStringLiteral( "PIXEL_COUNT" ), count );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
///@endcond
|
||||
|
||||
|
||||
|
82
src/analysis/processing/qgsalgorithmrastersurfacevolume.h
Normal file
82
src/analysis/processing/qgsalgorithmrastersurfacevolume.h
Normal file
@ -0,0 +1,82 @@
|
||||
/***************************************************************************
|
||||
qgsalgorithmrasterlayeruniquevalues.cpp
|
||||
---------------------
|
||||
begin : January 2019
|
||||
copyright : (C) 2019 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSALGORITHMRASTERSURFACEVOLUME_H
|
||||
#define QGSALGORITHMRASTERSURFACEVOLUME_H
|
||||
|
||||
#define SIP_NO_FILE
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgsprocessingalgorithm.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
/**
|
||||
* Native raster layer unique values report algorithm.
|
||||
*/
|
||||
class QgsRasterSurfaceVolumeAlgorithm : public QgsProcessingAlgorithm
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
QgsRasterSurfaceVolumeAlgorithm() = default;
|
||||
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
|
||||
QString name() const override;
|
||||
QString displayName() const override;
|
||||
QStringList tags() const override;
|
||||
QString group() const override;
|
||||
QString groupId() const override;
|
||||
QString shortHelpString() const override;
|
||||
QString shortDescription() const override;
|
||||
QgsRasterSurfaceVolumeAlgorithm *createInstance() const override SIP_FACTORY;
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
enum Method
|
||||
{
|
||||
CountOnlyAboveBaseLevel = 0,
|
||||
CountOnlyBelowBaseLevel,
|
||||
SubtractVolumesBelowBaseLevel,
|
||||
AddVolumesBelowBaseLevel
|
||||
};
|
||||
|
||||
std::unique_ptr< QgsRasterInterface > mInterface;
|
||||
bool mHasNoDataValue = false;
|
||||
int mBand = 1;
|
||||
int mLayerWidth;
|
||||
int mLayerHeight;
|
||||
QgsRectangle mExtent;
|
||||
QgsCoordinateReferenceSystem mCrs;
|
||||
double mRasterUnitsPerPixelX;
|
||||
double mRasterUnitsPerPixelY;
|
||||
double mLevel = 0;
|
||||
QString mSource;
|
||||
Method mMethod;
|
||||
|
||||
};
|
||||
|
||||
///@endcond PRIVATE
|
||||
|
||||
#endif // QGSALGORITHMRASTERSURFACEVOLUME_H
|
||||
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "qgsalgorithmprojectpointcartesian.h"
|
||||
#include "qgsalgorithmpromotetomultipart.h"
|
||||
#include "qgsalgorithmrasterlayeruniquevalues.h"
|
||||
#include "qgsalgorithmrastersurfacevolume.h"
|
||||
#include "qgsalgorithmrasterzonalstats.h"
|
||||
#include "qgsalgorithmreclassifybylayer.h"
|
||||
#include "qgsalgorithmremoveduplicatesbyattribute.h"
|
||||
@ -209,6 +210,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
|
||||
addAlgorithm( new QgsRasterLayerZonalStatsAlgorithm() );
|
||||
addAlgorithm( new QgsRasterPixelsToPointsAlgorithm() );
|
||||
addAlgorithm( new QgsRasterPixelsToPolygonsAlgorithm() );
|
||||
addAlgorithm( new QgsRasterSurfaceVolumeAlgorithm() );
|
||||
addAlgorithm( new QgsAlgorithmRemoveDuplicateVertices() );
|
||||
addAlgorithm( new QgsReclassifyByLayerAlgorithm() );
|
||||
addAlgorithm( new QgsReclassifyByTableAlgorithm() );
|
||||
|
Loading…
x
Reference in New Issue
Block a user