Add elevation utils method to collect significant elevation values for a project

This commit is contained in:
Nyall Dawson 2024-05-13 14:11:20 +10:00 committed by Martin Dobias
parent c8d66e1e8d
commit c79168a6bc
6 changed files with 173 additions and 0 deletions

View File

@ -28,6 +28,16 @@ Calculates the elevation range for a ``project``.
This method considers the elevation (or z) range available from layers contained within the project and This method considers the elevation (or z) range available from layers contained within the project and
returns the maximal combined elevation range of these layers. returns the maximal combined elevation range of these layers.
%End
static QList< double > significantZValuesForProject( QgsProject *project );
%Docstring
Returns a list of significant elevation/z-values for the specified ``project``, using
the values from layers contained by the project.
These values will be highlighted in elevation related widgets for the project.
.. versionadded:: 3.38
%End %End
static bool canEnableElevationForLayer( QgsMapLayer *layer ); static bool canEnableElevationForLayer( QgsMapLayer *layer );

View File

@ -28,6 +28,16 @@ Calculates the elevation range for a ``project``.
This method considers the elevation (or z) range available from layers contained within the project and This method considers the elevation (or z) range available from layers contained within the project and
returns the maximal combined elevation range of these layers. returns the maximal combined elevation range of these layers.
%End
static QList< double > significantZValuesForProject( QgsProject *project );
%Docstring
Returns a list of significant elevation/z-values for the specified ``project``, using
the values from layers contained by the project.
These values will be highlighted in elevation related widgets for the project.
.. versionadded:: 3.38
%End %End
static bool canEnableElevationForLayer( QgsMapLayer *layer ); static bool canEnableElevationForLayer( QgsMapLayer *layer );

View File

@ -54,6 +54,31 @@ QgsDoubleRange QgsElevationUtils::calculateZRangeForProject( QgsProject *project
std::isnan( max ) ? std::numeric_limits< double >::max() : max ); std::isnan( max ) ? std::numeric_limits< double >::max() : max );
} }
QList<double> QgsElevationUtils::significantZValuesForProject( QgsProject *project )
{
const QMap<QString, QgsMapLayer *> &mapLayers = project->mapLayers();
QSet< double > values;
QgsMapLayer *currentLayer = nullptr;
for ( QMap<QString, QgsMapLayer *>::const_iterator it = mapLayers.constBegin(); it != mapLayers.constEnd(); ++it )
{
currentLayer = it.value();
if ( !currentLayer->elevationProperties() || !currentLayer->elevationProperties()->hasElevation() )
continue;
const QList< double > layerValues = currentLayer->elevationProperties()->significantZValues( currentLayer );
for ( double value : layerValues )
{
values.insert( value );
}
}
QList< double > res = qgis::setToList( values );
std::sort( res.begin(), res.end() );
return res;
}
bool QgsElevationUtils::canEnableElevationForLayer( QgsMapLayer *layer ) bool QgsElevationUtils::canEnableElevationForLayer( QgsMapLayer *layer )
{ {
return static_cast< bool >( layer->elevationProperties() ); return static_cast< bool >( layer->elevationProperties() );

View File

@ -41,6 +41,16 @@ class CORE_EXPORT QgsElevationUtils
*/ */
static QgsDoubleRange calculateZRangeForProject( QgsProject *project ); static QgsDoubleRange calculateZRangeForProject( QgsProject *project );
/**
* Returns a list of significant elevation/z-values for the specified \a project, using
* the values from layers contained by the project.
*
* These values will be highlighted in elevation related widgets for the project.
*
* \since QGIS 3.38
*/
static QList< double > significantZValuesForProject( QgsProject *project );
/** /**
* Returns TRUE if elevation can be enabled for a map \a layer. * Returns TRUE if elevation can be enabled for a map \a layer.
* *

View File

@ -64,6 +64,7 @@ ADD_PYTHON_TEST(PyQgsDatumTransform test_qgsdatumtransforms.py)
ADD_PYTHON_TEST(PyQgsDelimitedTextProvider test_qgsdelimitedtextprovider.py) ADD_PYTHON_TEST(PyQgsDelimitedTextProvider test_qgsdelimitedtextprovider.py)
ADD_PYTHON_TEST(PyQgsDistanceArea test_qgsdistancearea.py) ADD_PYTHON_TEST(PyQgsDistanceArea test_qgsdistancearea.py)
ADD_PYTHON_TEST(PyQgsElevationControllerWidget test_qgselevationcontrollerwidget.py) ADD_PYTHON_TEST(PyQgsElevationControllerWidget test_qgselevationcontrollerwidget.py)
ADD_PYTHON_TEST(PyQgsElevationUtils test_qgselevationutils.py)
ADD_PYTHON_TEST(PyQgsEllipsoidUtils test_qgsellipsoidutils.py) ADD_PYTHON_TEST(PyQgsEllipsoidUtils test_qgsellipsoidutils.py)
ADD_PYTHON_TEST(PyQgsEmbeddedSymbolRenderer test_qgsembeddedsymbolrenderer.py) ADD_PYTHON_TEST(PyQgsEmbeddedSymbolRenderer test_qgsembeddedsymbolrenderer.py)
ADD_PYTHON_TEST(PyQgsExifTools test_qgsexiftools.py) ADD_PYTHON_TEST(PyQgsExifTools test_qgsexiftools.py)

View File

@ -0,0 +1,117 @@
"""QGIS Unit tests for QgsElevationUtils
.. note:: 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.
"""
import os
from qgis.core import (
Qgis,
QgsProject,
QgsRasterLayer,
QgsElevationUtils,
QgsDoubleRange
)
import unittest
from qgis.testing import start_app, QgisTestCase
from utilities import unitTestDataPath
# Convenience instances in case you may need them
# not used in this test
start_app()
TEST_DATA_DIR = unitTestDataPath()
class TestQgsElevationUtils(QgisTestCase):
def test_z_range_for_project(self):
"""
Test calculating z range for a project
"""
project = QgsProject()
self.assertEqual(
QgsElevationUtils.calculateZRangeForProject(project),
QgsDoubleRange())
raster_layer = QgsRasterLayer(os.path.join(unitTestDataPath(), 'landsat_4326.tif'))
self.assertTrue(raster_layer.isValid())
project.addMapLayer(raster_layer)
self.assertEqual(
QgsElevationUtils.calculateZRangeForProject(project),
QgsDoubleRange())
props = raster_layer.elevationProperties()
props.setEnabled(True)
props.setMode(Qgis.RasterElevationMode.FixedRangePerBand)
props.setFixedRangePerBand({1: QgsDoubleRange(103.1, 106.8),
2: QgsDoubleRange(106.8, 116.8),
3: QgsDoubleRange(116.8, 126.8)})
self.assertEqual(
QgsElevationUtils.calculateZRangeForProject(project),
QgsDoubleRange(103.1, 126.8))
raster_layer2 = QgsRasterLayer(os.path.join(unitTestDataPath(), 'landsat_4326.tif'))
self.assertTrue(raster_layer2.isValid())
project.addMapLayer(raster_layer2)
self.assertEqual(
QgsElevationUtils.calculateZRangeForProject(project),
QgsDoubleRange(103.1, 126.8))
props = raster_layer2.elevationProperties()
props.setEnabled(True)
props.setMode(Qgis.RasterElevationMode.FixedRangePerBand)
props.setFixedRangePerBand({1: QgsDoubleRange(103.1, 106.8),
2: QgsDoubleRange(106.8, 116.8),
3: QgsDoubleRange(126.8, 136.8)})
self.assertEqual(
QgsElevationUtils.calculateZRangeForProject(project),
QgsDoubleRange(103.1, 136.8))
def test_significant_z_values_for_project(self):
"""
Test calculating significant z values for a project
"""
project = QgsProject()
self.assertFalse(
QgsElevationUtils.significantZValuesForProject(project))
raster_layer = QgsRasterLayer(os.path.join(unitTestDataPath(), 'landsat_4326.tif'))
self.assertTrue(raster_layer.isValid())
project.addMapLayer(raster_layer)
self.assertFalse(
QgsElevationUtils.significantZValuesForProject(project))
props = raster_layer.elevationProperties()
props.setEnabled(True)
props.setMode(Qgis.RasterElevationMode.FixedRangePerBand)
props.setFixedRangePerBand({1: QgsDoubleRange(103.1, 106.8),
2: QgsDoubleRange(106.8, 116.8),
3: QgsDoubleRange(116.8, 126.8)})
self.assertEqual(
QgsElevationUtils.significantZValuesForProject(project),
[103.1, 106.8, 116.8, 126.8])
raster_layer2 = QgsRasterLayer(os.path.join(unitTestDataPath(), 'landsat_4326.tif'))
self.assertTrue(raster_layer2.isValid())
project.addMapLayer(raster_layer2)
self.assertEqual(
QgsElevationUtils.significantZValuesForProject(project),
[103.1, 106.8, 116.8, 126.8])
props = raster_layer2.elevationProperties()
props.setEnabled(True)
props.setMode(Qgis.RasterElevationMode.FixedRangePerBand)
props.setFixedRangePerBand({1: QgsDoubleRange(103.1, 106.8),
2: QgsDoubleRange(106.8, 116.8),
3: QgsDoubleRange(126.8, 136.8)})
self.assertEqual(
QgsElevationUtils.significantZValuesForProject(project),
[103.1, 106.8, 116.8, 126.8, 136.8])
if __name__ == '__main__':
unittest.main()