Skip to content

Commit d5ce6dc

Browse files
committedJul 30, 2018
[FEATURE][processing] native drape features to z/m algorithms
Sets vertex z/m values to values sampled from a raster band. Values can optionally be scaled using a (data definable) scale value.
1 parent d09faf4 commit d5ce6dc

31 files changed

+448
-0
lines changed
 
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
UTF-8
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PROJCS["WGS_1984_Web_Mercator_Auxiliary_Sphere",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Mercator_Auxiliary_Sphere"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",0.0],PARAMETER["Standard_Parallel_1",0.0],PARAMETER["Auxiliary_Sphere_Type",0.0],UNIT["Meter",1.0]]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",EAST],AXIS["Y",NORTH],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3857"]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PROJCS["WGS_1984_Web_Mercator_Auxiliary_Sphere",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Mercator_Auxiliary_Sphere"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",0.0],PARAMETER["Standard_Parallel_1",0.0],PARAMETER["Auxiliary_Sphere_Type",0.0],UNIT["Meter",1.0]]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",EAST],AXIS["Y",NORTH],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3857"]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PROJCS["WGS_1984_Web_Mercator_Auxiliary_Sphere",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Mercator_Auxiliary_Sphere"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",0.0],PARAMETER["Standard_Parallel_1",0.0],PARAMETER["Auxiliary_Sphere_Type",0.0],UNIT["Meter",1.0]]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",EAST],AXIS["Y",NORTH],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3857"]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]
Binary file not shown.
Binary file not shown.

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5924,4 +5924,74 @@ tests:
59245924
name: expected/create_parallel_lines.gml
59255925
type: vector
59265926

5927+
- algorithm: native:drapetoz
5928+
name: Drape points to z
5929+
params:
5930+
BAND: 1
5931+
INPUT:
5932+
name: custom/sampling_points.gml
5933+
type: vector
5934+
NODATA: 0.0
5935+
RASTER:
5936+
name: dem.tif
5937+
type: raster
5938+
SCALE: 1.2
5939+
results:
5940+
OUTPUT:
5941+
name: expected/drape_points.shp
5942+
type: vector
5943+
5944+
- algorithm: native:drapetom
5945+
name: Drape points to m
5946+
params:
5947+
BAND: 1
5948+
INPUT:
5949+
name: custom/sampling_points.gml
5950+
type: vector
5951+
NODATA: 0.0
5952+
RASTER:
5953+
name: dem.tif
5954+
type: raster
5955+
SCALE: 1.2
5956+
results:
5957+
OUTPUT:
5958+
name: expected/drape_points_m.shp
5959+
type: vector
5960+
5961+
- algorithm: native:drapetoz
5962+
name: Drape lines to z
5963+
params:
5964+
BAND: 1
5965+
INPUT:
5966+
name: custom/dem_lines.shp
5967+
type: vector
5968+
NODATA: -9999.0
5969+
RASTER:
5970+
name: dem.tif
5971+
type: raster
5972+
SCALE: 1.0
5973+
results:
5974+
OUTPUT:
5975+
name: expected/drape_lines.shp
5976+
type: vector
5977+
5978+
- algorithm: native:drapetom
5979+
name: Drape lines to m
5980+
params:
5981+
BAND: 1
5982+
INPUT:
5983+
name: custom/dem_lines.shp
5984+
type: vector
5985+
NODATA: -9999.0
5986+
RASTER:
5987+
name: dem.tif
5988+
type: raster
5989+
SCALE: 1.0
5990+
results:
5991+
OUTPUT:
5992+
name: expected/drape_lines_m.shp
5993+
type: vector
5994+
5995+
5996+
59275997
# See ../README.md for a description of the file format

‎src/analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ SET(QGIS_ANALYSIS_SRCS
3131
processing/qgsalgorithmdbscanclustering.cpp
3232
processing/qgsalgorithmdifference.cpp
3333
processing/qgsalgorithmdissolve.cpp
34+
processing/qgsalgorithmdrape.cpp
3435
processing/qgsalgorithmdropgeometry.cpp
3536
processing/qgsalgorithmdropmzvalues.cpp
3637
processing/qgsalgorithmexplode.cpp
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
/***************************************************************************
2+
qgsalgorithmdrape.cpp
3+
---------------------
4+
begin : November 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include "qgsalgorithmdrape.h"
19+
20+
///@cond PRIVATE
21+
22+
23+
QString QgsDrapeAlgorithmBase::group() const
24+
{
25+
return QObject::tr( "Vector geometry" );
26+
}
27+
28+
QString QgsDrapeAlgorithmBase::groupId() const
29+
{
30+
return QStringLiteral( "vectorgeometry" );
31+
}
32+
33+
QString QgsDrapeAlgorithmBase::outputName() const
34+
{
35+
return QObject::tr( "Draped" );
36+
}
37+
38+
void QgsDrapeAlgorithmBase::initParameters( const QVariantMap & )
39+
{
40+
addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "RASTER" ),
41+
QObject::tr( "Raster layer" ) ) );
42+
addParameter( new QgsProcessingParameterBand( QStringLiteral( "BAND" ),
43+
QObject::tr( "Band number" ), 1, QStringLiteral( "RASTER" ) ) );
44+
45+
// nodata value
46+
std::unique_ptr< QgsProcessingParameterNumber > nodata = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "NODATA" ),
47+
QObject::tr( "Value for nodata or non-intersecting vertices" ), QgsProcessingParameterNumber::Double,
48+
0.0 );
49+
nodata->setIsDynamic( true );
50+
nodata->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "NODATA" ), QObject::tr( "Value for nodata or non-intersecting vertices" ), QgsPropertyDefinition::Double ) );
51+
nodata->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
52+
addParameter( nodata.release() );
53+
54+
auto scaleParam = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "SCALE" ), QObject::tr( "Scale factor" ), QgsProcessingParameterNumber::Double, 1.0, false, 0.0 );
55+
scaleParam->setIsDynamic( true );
56+
scaleParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "SCALE" ), QObject::tr( "Scale factor" ), QgsPropertyDefinition::Double ) );
57+
scaleParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
58+
addParameter( scaleParam.release() );
59+
}
60+
61+
bool QgsDrapeAlgorithmBase::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
62+
{
63+
mNoData = parameterAsDouble( parameters, QStringLiteral( "NODATA" ), context );
64+
mDynamicNoData = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "NODATA" ) );
65+
if ( mDynamicNoData )
66+
mNoDataProperty = parameters.value( QStringLiteral( "NODATA" ) ).value< QgsProperty >();
67+
68+
mScale = parameterAsDouble( parameters, QStringLiteral( "SCALE" ), context );
69+
mDynamicScale = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "SCALE" ) );
70+
if ( mDynamicScale )
71+
mScaleProperty = parameters.value( QStringLiteral( "SCALE" ) ).value< QgsProperty >();
72+
73+
QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "RASTER" ), context );
74+
75+
if ( !layer )
76+
throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "RASTER" ) ) );
77+
78+
mBand = parameterAsInt( parameters, QStringLiteral( "BAND" ), context );
79+
if ( mBand < 1 || mBand > layer->bandCount() )
80+
throw QgsProcessingException( QObject::tr( "Invalid band number for BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand )
81+
.arg( layer->bandCount() ) );
82+
83+
std::unique_ptr< QgsRasterInterface > provider( layer->dataProvider()->clone() );
84+
QgsRasterDataProvider *dp = dynamic_cast< QgsRasterDataProvider * >( provider.get() );
85+
if ( !dp )
86+
throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "RASTER" ) ) );
87+
88+
mRasterProvider.reset( dp );
89+
provider.release();
90+
91+
return true;
92+
}
93+
94+
QgsFeatureList QgsDrapeAlgorithmBase::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
95+
{
96+
if ( !mCreatedTransform )
97+
{
98+
mCreatedTransform = true;
99+
mTransform = QgsCoordinateTransform( sourceCrs(), mRasterProvider->crs(), context.transformContext() );
100+
}
101+
102+
QgsFeature f = feature;
103+
if ( f.hasGeometry() )
104+
{
105+
QgsGeometry geometry = f.geometry();
106+
107+
double nodata = mNoData;
108+
if ( mDynamicNoData )
109+
nodata = mNoDataProperty.valueAsDouble( context.expressionContext(), nodata );
110+
111+
double scale = mScale;
112+
if ( mDynamicScale )
113+
scale = mScaleProperty.valueAsDouble( context.expressionContext(), scale );
114+
115+
prepareGeometry( geometry, nodata );
116+
117+
geometry.transformVertices( [ = ]( const QgsPoint & p )->QgsPoint
118+
{
119+
QgsPointXY t;
120+
double val = nodata;
121+
try
122+
{
123+
t = mTransform.transform( p );
124+
bool ok = false;
125+
val = mRasterProvider->sample( t, mBand, &ok );
126+
if ( !ok )
127+
val = nodata;
128+
else
129+
val *= scale;
130+
}
131+
catch ( QgsCsException & )
132+
{
133+
feedback->reportError( QObject::tr( "Transform error while reprojecting feature {}" ).arg( f.id() ) );
134+
}
135+
136+
return drapeVertex( p, val );
137+
} );
138+
139+
f.setGeometry( geometry );
140+
}
141+
return QgsFeatureList() << f;
142+
}
143+
144+
145+
//
146+
// QgsDrapeToZAlgorithm
147+
//
148+
149+
QString QgsDrapeToZAlgorithm::name() const
150+
{
151+
return QStringLiteral( "drapetoz" );
152+
}
153+
154+
QString QgsDrapeToZAlgorithm::displayName() const
155+
{
156+
return QObject::tr( "Drape (Sample raster to z)" );
157+
}
158+
159+
QStringList QgsDrapeToZAlgorithm::tags() const
160+
{
161+
return QObject::tr( "3d,vertex,vertices,elevation,sample" ).split( ',' );
162+
}
163+
164+
QString QgsDrapeToZAlgorithm::shortHelpString() const
165+
{
166+
return QObject::tr( "This algorithm sets the z value of every vertex in the feature geometry to a value sampled from a band within a raster layer." )
167+
+ QStringLiteral( "\n\n" )
168+
+ QObject::tr( "The raster values can optionally be scaled by a preset amount." );
169+
}
170+
171+
QString QgsDrapeToZAlgorithm::shortDescription() const
172+
{
173+
return QObject::tr( "Sets the z value for vertices to values sampled from a raster layer." );
174+
}
175+
176+
QgsDrapeToZAlgorithm *QgsDrapeToZAlgorithm::createInstance() const
177+
{
178+
return new QgsDrapeToZAlgorithm();
179+
}
180+
181+
QgsWkbTypes::Type QgsDrapeToZAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
182+
{
183+
QgsWkbTypes::Type wkb = inputWkbType;
184+
return QgsWkbTypes::addZ( wkb );
185+
}
186+
187+
void QgsDrapeToZAlgorithm::prepareGeometry( QgsGeometry &geometry, double defaultVal ) const
188+
{
189+
geometry.get()->addZValue( defaultVal );
190+
}
191+
192+
QgsPoint QgsDrapeToZAlgorithm::drapeVertex( const QgsPoint &p, double rasterVal ) const
193+
{
194+
return QgsPoint( p.wkbType(), p.x(), p.y(), rasterVal, p.m() );
195+
}
196+
197+
//
198+
// QgsDrapeToMAlgorithm
199+
//
200+
201+
QString QgsDrapeToMAlgorithm::name() const
202+
{
203+
return QStringLiteral( "drapetom" );
204+
}
205+
206+
QString QgsDrapeToMAlgorithm::displayName() const
207+
{
208+
return QObject::tr( "Sample raster to m-values" );
209+
}
210+
211+
QStringList QgsDrapeToMAlgorithm::tags() const
212+
{
213+
return QObject::tr( "vertex,vertices,sample,measure" ).split( ',' );
214+
}
215+
216+
QString QgsDrapeToMAlgorithm::shortHelpString() const
217+
{
218+
return QObject::tr( "This algorithm sets the m-value for every vertex in the feature geometry to a value sampled from a band within a raster layer." )
219+
+ QStringLiteral( "\n\n" )
220+
+ QObject::tr( "The raster values can optionally be scaled by a preset amount." );
221+
}
222+
223+
QString QgsDrapeToMAlgorithm::shortDescription() const
224+
{
225+
return QObject::tr( "Sets the m-value for vertices to values sampled from a raster layer." );
226+
}
227+
228+
QgsDrapeToMAlgorithm *QgsDrapeToMAlgorithm::createInstance() const
229+
{
230+
return new QgsDrapeToMAlgorithm();
231+
}
232+
233+
QgsWkbTypes::Type QgsDrapeToMAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
234+
{
235+
QgsWkbTypes::Type wkb = inputWkbType;
236+
return QgsWkbTypes::addM( wkb );
237+
}
238+
239+
void QgsDrapeToMAlgorithm::prepareGeometry( QgsGeometry &geometry, double defaultVal ) const
240+
{
241+
geometry.get()->addMValue( defaultVal );
242+
}
243+
244+
QgsPoint QgsDrapeToMAlgorithm::drapeVertex( const QgsPoint &p, double rasterVal ) const
245+
{
246+
return QgsPoint( p.wkbType(), p.x(), p.y(), p.z(), rasterVal );
247+
}
248+
249+
250+
///@endcond
251+
252+

0 commit comments

Comments
 (0)