Skip to content

Commit e91ee5b

Browse files
committed
More flexible API for interpolation
E.g. adds API support for interpolating by m value
1 parent 73306f1 commit e91ee5b

File tree

9 files changed

+105
-51
lines changed

9 files changed

+105
-51
lines changed

doc/api_break.dox

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1490,7 +1490,7 @@ QgsInterpolator {#qgis_api_break_3_0_QgsInterpolator}
14901490

14911491
- The InputType enum was renamed to SourceType and the enum values were renamed.
14921492
- LayerData.vectorLayer was renamed to LayerData.source
1493-
- LayerData.zCoordInterpolation was renamed to LayerData.useZValue
1493+
- LayerData.zCoordInterpolation was renamed to LayerData.valueSource and now takes a QgsInterpolator.ValueSource enum value.
14941494
- LayerData.mInputType was renamed to LayerData.sourceType
14951495

14961496

python/analysis/interpolation/qgsinterpolator.sip

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ class QgsInterpolator
5858
SourceBreakLines,
5959
};
6060

61+
enum ValueSource
62+
{
63+
ValueAttribute,
64+
ValueZ,
65+
ValueM,
66+
};
67+
6168
enum Result
6269
{
6370
Success,
@@ -72,9 +79,9 @@ class QgsInterpolator
7279
%Docstring
7380
Feature source
7481
%End
75-
bool useZValue;
82+
ValueSource valueSource;
7683
%Docstring
77-
True if feature geometry z values should be used for interpolation
84+
Source for feature values to interpolate
7885
%End
7986
int interpolationAttribute;
8087
%Docstring

python/plugins/processing/algs/qgis/IdwInterpolation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def processAlgorithm(self, parameters, context, feedback):
159159
data.source = layer
160160
layers.append(layer)
161161

162-
data.useZValue = bool(v[1])
162+
data.valueSource = int(v[1])
163163
data.interpolationAttribute = int(v[2])
164164
if v[3] == '0':
165165
data.sourceType = QgsInterpolator.SourcePoints

python/plugins/processing/algs/qgis/TinInterpolation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def processAlgorithm(self, parameters, context, feedback):
181181
if not crs.isValid():
182182
crs = layer.sourceCrs()
183183

184-
data.useZValue = bool(v[1])
184+
data.valueSource = int(v[1])
185185
data.interpolationAttribute = int(v[2])
186186
if v[3] == '0':
187187
data.sourceType = QgsInterpolator.SourcePoints

python/plugins/processing/algs/qgis/ui/InterpolationDataWidget.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,11 @@ def value(self):
136136
continue
137137

138138
interpolationAttribute = item.text(1)
139+
interpolationSource = QgsInterpolator.ValueAttribute
139140
if interpolationAttribute == 'Z_COORD':
140-
zCoord = True
141+
interpolationSource = QgsInterpolator.ValueZ
141142
fieldIndex = -1
142143
else:
143-
zCoord = False
144144
fieldIndex = layer.fields().indexFromName(interpolationAttribute)
145145

146146
comboBox = self.layersTree.itemWidget(self.layersTree.topLevelItem(i), 2)
@@ -152,10 +152,10 @@ def value(self):
152152
else:
153153
inputType = QgsInterpolator.SourceBreakLines
154154

155-
layers += '{},{},{:d},{:d};'.format(layer.source(),
156-
zCoord,
157-
fieldIndex,
158-
inputType)
155+
layers += '{},{:d},{:d},{:d};'.format(layer.source(),
156+
interpolationSource,
157+
fieldIndex,
158+
inputType)
159159
return layers[:-1]
160160

161161

src/analysis/interpolation/qgsinterpolator.cpp

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,15 @@ QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback )
5353
}
5454

5555
QgsAttributeList attList;
56-
if ( !layer.useZValue )
56+
switch ( layer.valueSource )
5757
{
58-
attList.push_back( layer.interpolationAttribute );
58+
case ValueAttribute:
59+
attList.push_back( layer.interpolationAttribute );
60+
break;
61+
62+
case ValueZ:
63+
case ValueM:
64+
break;
5965
}
6066

6167
double attributeValue = 0.0;
@@ -75,21 +81,29 @@ QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback )
7581
if ( feedback )
7682
feedback->setProgress( progress );
7783

78-
if ( !layer.useZValue )
84+
switch ( layer.valueSource )
7985
{
80-
QVariant attributeVariant = feature.attribute( layer.interpolationAttribute );
81-
if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value)
82-
{
83-
continue;
84-
}
85-
attributeValue = attributeVariant.toDouble( &attributeConversionOk );
86-
if ( !attributeConversionOk || std::isnan( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
86+
case ValueAttribute:
8787
{
88-
continue;
88+
QVariant attributeVariant = feature.attribute( layer.interpolationAttribute );
89+
if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value)
90+
{
91+
continue;
92+
}
93+
attributeValue = attributeVariant.toDouble( &attributeConversionOk );
94+
if ( !attributeConversionOk || std::isnan( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
95+
{
96+
continue;
97+
}
98+
break;
8999
}
100+
101+
case ValueZ:
102+
case ValueM:
103+
break;
90104
}
91105

92-
if ( !addVerticesToCache( feature.geometry(), layer.useZValue, attributeValue ) )
106+
if ( !addVerticesToCache( feature.geometry(), layer.valueSource, attributeValue ) )
93107
return FeatureGeometryError;
94108
}
95109
layerCount++;
@@ -98,21 +112,45 @@ QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback )
98112
return Success;
99113
}
100114

101-
bool QgsInterpolator::addVerticesToCache( const QgsGeometry &geom, bool zCoord, double attributeValue )
115+
bool QgsInterpolator::addVerticesToCache( const QgsGeometry &geom, ValueSource source, double attributeValue )
102116
{
103117
if ( !geom || geom.isEmpty() )
104118
return true; // nothing to do
105119

106-
bool hasZ = geom.constGet()->is3D();
120+
//validate source
121+
switch ( source )
122+
{
123+
case ValueAttribute:
124+
break;
125+
126+
case ValueM:
127+
if ( !geom.constGet()->isMeasure() )
128+
return false;
129+
else
130+
break;
131+
132+
case ValueZ:
133+
if ( !geom.constGet()->is3D() )
134+
return false;
135+
else
136+
break;
137+
}
138+
107139
for ( auto point = geom.vertices_begin(); point != geom.vertices_end(); ++point )
108140
{
109-
if ( hasZ && zCoord )
110-
{
111-
mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).z() ) );
112-
}
113-
else
141+
switch ( source )
114142
{
115-
mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), attributeValue ) );
143+
case ValueM:
144+
mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).m() ) );
145+
break;
146+
147+
case ValueZ:
148+
mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).z() ) );
149+
break;
150+
151+
case ValueAttribute:
152+
mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), attributeValue ) );
153+
break;
116154
}
117155
}
118156
mDataIsCached = true;

src/analysis/interpolation/qgsinterpolator.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,14 @@ class ANALYSIS_EXPORT QgsInterpolator
7272
SourceBreakLines, //!< Break lines
7373
};
7474

75+
//! Source for interpolated values from features
76+
enum ValueSource
77+
{
78+
ValueAttribute, //!< Take value from feature's attribute
79+
ValueZ, //!< Use feature's geometry Z values for interpolation
80+
ValueM, //!< Use feature's geometry M values for interpolation
81+
};
82+
7583
//! Result of an interpolation operation
7684
enum Result
7785
{
@@ -86,8 +94,8 @@ class ANALYSIS_EXPORT QgsInterpolator
8694
{
8795
//! Feature source
8896
QgsFeatureSource *source = nullptr;
89-
//! True if feature geometry z values should be used for interpolation
90-
bool useZValue = false;
97+
//! Source for feature values to interpolate
98+
ValueSource valueSource = ValueAttribute;
9199
//! Index of feature attribute to use for interpolation
92100
int interpolationAttribute = -1;
93101
//! Source type
@@ -138,11 +146,11 @@ class ANALYSIS_EXPORT QgsInterpolator
138146
/**
139147
* Helper method that adds the vertices of a geometry to the mCachedBaseData
140148
* \param geom the geometry
141-
* \param zCoord true if the z-coordinate of the geometry is to be interpolated
142-
* \param attributeValue the attribute value for interpolation (if not interpolated from z-coordinate)
149+
* \param source source for values to interpolate from the feature
150+
* \param attributeValue the attribute value for interpolation (if interpolating from attribute value)
143151
*\returns 0 in case of success
144152
*/
145-
bool addVerticesToCache( const QgsGeometry &geom, bool zCoord, double attributeValue );
153+
bool addVerticesToCache( const QgsGeometry &geom, ValueSource source, double attributeValue );
146154
};
147155

148156
#endif

src/analysis/interpolation/qgstininterpolator.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ void QgsTINInterpolator::initialize()
9393
int nProcessedFeatures = 0;
9494
if ( mFeedback )
9595
{
96-
Q_FOREACH ( const LayerData &layer, mLayerData )
96+
for ( const LayerData &layer : qgis::as_const( mLayerData ) )
9797
{
9898
if ( layer.source )
9999
{
@@ -103,14 +103,20 @@ void QgsTINInterpolator::initialize()
103103
}
104104

105105
QgsFeature f;
106-
Q_FOREACH ( const LayerData &layer, mLayerData )
106+
for ( const LayerData &layer : qgis::as_const( mLayerData ) )
107107
{
108108
if ( layer.source )
109109
{
110110
QgsAttributeList attList;
111-
if ( !layer.useZValue )
111+
switch ( layer.valueSource )
112112
{
113-
attList.push_back( layer.interpolationAttribute );
113+
case QgsInterpolator::ValueAttribute:
114+
attList.push_back( layer.interpolationAttribute );
115+
break;
116+
117+
case QgsInterpolator::ValueM:
118+
case QgsInterpolator::ValueZ:
119+
break;
114120
}
115121

116122
QgsFeatureIterator fit = layer.source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ) );
@@ -126,7 +132,7 @@ void QgsTINInterpolator::initialize()
126132
if ( nFeatures > 0 )
127133
mFeedback->setProgress( 100.0 * static_cast< double >( nProcessedFeatures ) / nFeatures );
128134
}
129-
insertData( &f, layer.useZValue, layer.interpolationAttribute, layer.sourceType );
135+
insertData( f, layer.valueSource, layer.interpolationAttribute, layer.sourceType );
130136
++nProcessedFeatures;
131137
}
132138
}
@@ -157,16 +163,11 @@ void QgsTINInterpolator::initialize()
157163
}
158164
}
159165

160-
int QgsTINInterpolator::insertData( QgsFeature *f, bool zCoord, int attr, SourceType type )
166+
int QgsTINInterpolator::insertData( const QgsFeature &f, bool zCoord, int attr, SourceType type )
161167
{
162-
if ( !f )
163-
{
164-
return 1;
165-
}
166-
167-
QgsGeometry g = f->geometry();
168+
QgsGeometry g = f.geometry();
168169
{
169-
if ( g.isNull() )
170+
if ( g.isNull() || g.isEmpty() )
170171
{
171172
return 2;
172173
}
@@ -177,7 +178,7 @@ int QgsTINInterpolator::insertData( QgsFeature *f, bool zCoord, int attr, Source
177178
bool attributeConversionOk = false;
178179
if ( !zCoord )
179180
{
180-
QVariant attributeVariant = f->attribute( attr );
181+
QVariant attributeVariant = f.attribute( attr );
181182
if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value)
182183
{
183184
return 3;

src/analysis/interpolation/qgstininterpolator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class ANALYSIS_EXPORT QgsTINInterpolator: public QgsInterpolator
9393
\param attr interpolation attribute index (if zCoord is false)
9494
\param type point/structure line, break line
9595
\returns 0 in case of success, -1 if the feature could not be inserted because of numerical problems*/
96-
int insertData( QgsFeature *f, bool zCoord, int attr, SourceType type );
96+
int insertData( const QgsFeature &f, bool zCoord, int attr, SourceType type );
9797
};
9898

9999
#endif

0 commit comments

Comments
 (0)