Skip to content

Commit

Permalink
Use QgsFeatureSources instead of QgsVectorLayer for interpolation
Browse files Browse the repository at this point in the history
source layers
  • Loading branch information
nyalldawson committed Nov 2, 2017
1 parent 28ee440 commit b369ef8
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 41 deletions.
4 changes: 2 additions & 2 deletions src/analysis/interpolation/qgsgridfilewriter.cpp
Expand Up @@ -87,8 +87,8 @@ int QgsGridFileWriter::writeFile( QgsFeedback *feedback )
// create prj file
QgsInterpolator::LayerData ld;
ld = mInterpolator->layerData().at( 0 );
QgsVectorLayer *vl = ld.vectorLayer;
QString crs = vl->crs().toWkt();
QgsFeatureSource *source = ld.source;
QString crs = source->sourceCrs().toWkt();
QFileInfo fi( mOutputFilePath );
QString fileName = fi.absolutePath() + '/' + fi.completeBaseName() + ".prj";
QFile prjFile( fileName );
Expand Down
38 changes: 26 additions & 12 deletions src/analysis/interpolation/qgsidwinterpolator.h
Expand Up @@ -24,32 +24,46 @@
/**
* \ingroup analysis
* \class QgsIDWInterpolator
* Inverse distance weight interpolator.
*/
class ANALYSIS_EXPORT QgsIDWInterpolator: public QgsInterpolator
{
public:

/**
* Constructor for QgsIDWInterpolator, with the specified \a layerData sources.
*/
QgsIDWInterpolator( const QList<QgsInterpolator::LayerData> &layerData );

int interpolatePoint( double x, double y, double &result, QgsFeedback *feedback = nullptr ) override;

/**
* Calculates interpolation value for map coordinates x, y
\param x x-coordinate (in map units)
\param y y-coordinate (in map units)
\param result out: interpolation result
\returns 0 in case of success*/
int interpolatePoint( double x, double y, double &result ) override;
* Sets the distance \a coefficient, the parameter that sets how the values are
* weighted with distance. Smaller values mean sharper peaks at the data points.
*
* Point values are weighted by 1 / ( distance ^ coefficient ).
*
* \see distanceCoefficient()
* \since QGIS 3.0
*/
void setDistanceCoefficient( double coefficient ) { mDistanceCoefficient = coefficient;}

void setDistanceCoefficient( double p ) {mDistanceCoefficient = p;}
/**
* Returns the distance coefficient, the parameter that sets how the values are
* weighted with distance. Smaller values mean sharper peaks at the data points.
* The default is a coefficient of 2.
*
* Point values are weighted by 1 / ( distance ^ coefficient ).
*
* \see setDistanceCoefficient()
* \since QGIS 3.0
*/
double distanceCoefficient() const { return mDistanceCoefficient; }

private:

QgsIDWInterpolator(); //forbidden
QgsIDWInterpolator() = delete;

/**
* The parameter that sets how the values are weighted with distance.
Smaller values mean sharper peaks at the data points. The default is a
value of 2*/
double mDistanceCoefficient = 2.0;
};

Expand Down
22 changes: 11 additions & 11 deletions src/analysis/interpolation/qgsinterpolator.cpp
Expand Up @@ -39,29 +39,30 @@ QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback )
mCachedBaseData.clear();
mCachedBaseData.reserve( 100000 );

Q_FOREACH ( const LayerData &layer, mLayerData )
double layerStep = !mLayerData.empty() ? 100.0 / mLayerData.count() : 1;
int layerCount = 0;
for ( const LayerData &layer : qgis::as_const( mLayerData ) )
{
if ( feedback && feedback->isCanceled() )
return Canceled;

QgsVectorLayer *vlayer = layer.vectorLayer;
if ( !vlayer )
QgsFeatureSource *source = layer.source;
if ( !source )
{
return 2;
}

QgsAttributeList attList;
if ( !layer.zCoordInterpolation )
if ( !layer.useZValue )
{
attList.push_back( layer.interpolationAttribute );
}


double attributeValue = 0.0;
bool attributeConversionOk = false;
double progress = layerCount * layerStep;

QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ) );
QgsFeatureIterator fit = source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ) );
double featureStep = source->featureCount() > 0 ? layerStep / source->featureCount() : layerStep;

QgsFeature feature;
Expand All @@ -74,7 +75,7 @@ QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback )
if ( feedback )
feedback->setProgress( progress );

if ( !layer.zCoordInterpolation )
if ( !layer.useZValue )
{
QVariant attributeVariant = feature.attribute( layer.interpolationAttribute );
if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value)
Expand All @@ -88,11 +89,10 @@ QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback )
}
}

if ( addVerticesToCache( feature.geometry(), layer.zCoordInterpolation, attributeValue ) != 0 )
{
return 3;
}
if ( !addVerticesToCache( feature.geometry(), layer.useZValue, attributeValue ) )
return FeatureGeometryError;
}
layerCount++;
}

return 0;
Expand Down
29 changes: 19 additions & 10 deletions src/analysis/interpolation/qgsinterpolator.h
Expand Up @@ -22,7 +22,7 @@
#include "qgis_sip.h"
#include "qgis_analysis.h"

class QgsVectorLayer;
class QgsFeatureSource;
class QgsGeometry;
class QgsFeedback;

Expand Down Expand Up @@ -58,9 +58,12 @@ class ANALYSIS_EXPORT QgsInterpolator
//! A layer together with the information about interpolation attribute / z-coordinate interpolation and the type (point, structure line, breakline)
struct LayerData
{
QgsVectorLayer *vectorLayer = nullptr;
bool zCoordInterpolation;
int interpolationAttribute;
//! Feature source
QgsFeatureSource *source = nullptr;
//! True if feature geometry z values should be used for interpolation
bool useZValue = false;
//! Index of feature attribute to use for interpolation
int interpolationAttribute = -1;
//! Source type
QgsInterpolator::SourceType sourceType = SourcePoints;
};
Expand All @@ -85,16 +88,22 @@ class ANALYSIS_EXPORT QgsInterpolator

/**
* Caches the vertex and value data from the provider. All the vertex data
will be held in virtual memory
\returns 0 in case of success*/
int cacheBaseData();

QVector<vertexData> mCachedBaseData;
* will be held in virtual memory.
*
* An optional \a feedback argument may be specified to allow cancelation and
* progress reports from the cache operation.
*
* \returns Success in case of success
*/
Result cacheBaseData( QgsFeedback *feedback = nullptr );

//! Cached vertex data for input sources
QVector<QgsInterpolatorVertexData> mCachedBaseData;

//! Flag that tells if the cache already has been filled
bool mDataIsCached = false;

//Information about the input vector layers and the attributes (or z-values) that are used for interpolation
//! Information about the input vector layers and the attributes (or z-values) that are used for interpolation
QList<LayerData> mLayerData;

private:
Expand Down
12 changes: 6 additions & 6 deletions src/analysis/interpolation/qgstininterpolator.cpp
Expand Up @@ -95,25 +95,25 @@ void QgsTINInterpolator::initialize()
{
Q_FOREACH ( const LayerData &layer, mLayerData )
{
if ( layer.vectorLayer )
if ( layer.source )
{
nFeatures += layer.vectorLayer->featureCount();
nFeatures += layer.source->featureCount();
}
}
}

QgsFeature f;
Q_FOREACH ( const LayerData &layer, mLayerData )
{
if ( layer.vectorLayer )
if ( layer.source )
{
QgsAttributeList attList;
if ( !layer.zCoordInterpolation )
if ( !layer.useZValue )
{
attList.push_back( layer.interpolationAttribute );
}

QgsFeatureIterator fit = layer.vectorLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ) );
QgsFeatureIterator fit = layer.source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ) );

while ( fit.nextFeature( f ) )
{
Expand All @@ -126,7 +126,7 @@ void QgsTINInterpolator::initialize()
if ( nFeatures > 0 )
mFeedback->setProgress( 100.0 * static_cast< double >( nProcessedFeatures ) / nFeatures );
}
insertData( &f, layer.zCoordInterpolation, layer.interpolationAttribute, layer.mInputType );
insertData( &f, layer.useZValue, layer.interpolationAttribute, layer.sourceType );
++nProcessedFeatures;
}
}
Expand Down

0 comments on commit b369ef8

Please sign in to comment.