Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsinterpolator.cpp 3 : : ------------------- 4 : : begin : Marco 10, 2008 5 : : copyright : (C) 2008 by Marco Hugentobler 6 : : email : marco dot hugentobler at karto dot baug dot ethz dot ch 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 "qgsinterpolator.h" 19 : : #include "qgsfeatureiterator.h" 20 : : #include "qgsvectordataprovider.h" 21 : : #include "qgsvectorlayer.h" 22 : : #include "qgsgeometry.h" 23 : : #include "qgsfeedback.h" 24 : : 25 : 0 : QgsInterpolator::QgsInterpolator( const QList<LayerData> &layerData ) 26 : 0 : : mLayerData( layerData ) 27 : 0 : { 28 : : 29 : 0 : } 30 : : 31 : 0 : QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback ) 32 : : { 33 : 0 : if ( mLayerData.empty() ) 34 : : { 35 : 0 : return Success; 36 : : } 37 : : 38 : : //reserve initial memory for 100000 vertices 39 : 0 : mCachedBaseData.clear(); 40 : 0 : mCachedBaseData.reserve( 100000 ); 41 : : 42 : 0 : const QgsCoordinateReferenceSystem crs = !mLayerData.empty() ? mLayerData.at( 0 ).source->sourceCrs() : QgsCoordinateReferenceSystem(); 43 : : 44 : 0 : double layerStep = !mLayerData.empty() ? 100.0 / mLayerData.count() : 1; 45 : 0 : int layerCount = 0; 46 : 0 : for ( const LayerData &layer : std::as_const( mLayerData ) ) 47 : : { 48 : 0 : if ( feedback && feedback->isCanceled() ) 49 : 0 : return Canceled; 50 : : 51 : 0 : QgsFeatureSource *source = layer.source; 52 : 0 : if ( !source ) 53 : : { 54 : 0 : return InvalidSource; 55 : : } 56 : : 57 : 0 : QgsAttributeList attList; 58 : 0 : switch ( layer.valueSource ) 59 : : { 60 : : case ValueAttribute: 61 : 0 : attList.push_back( layer.interpolationAttribute ); 62 : 0 : break; 63 : : 64 : : case ValueZ: 65 : : case ValueM: 66 : 0 : break; 67 : : } 68 : : 69 : 0 : double attributeValue = 0.0; 70 : 0 : bool attributeConversionOk = false; 71 : 0 : double progress = layerCount * layerStep; 72 : : 73 : 0 : QgsFeatureIterator fit = source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ).setDestinationCrs( crs, layer.transformContext ) ); 74 : 0 : double featureStep = source->featureCount() > 0 ? layerStep / source->featureCount() : layerStep; 75 : : 76 : 0 : QgsFeature feature; 77 : 0 : while ( fit.nextFeature( feature ) ) 78 : : { 79 : 0 : if ( feedback && feedback->isCanceled() ) 80 : 0 : return Canceled; 81 : : 82 : 0 : progress += featureStep; 83 : 0 : if ( feedback ) 84 : 0 : feedback->setProgress( progress ); 85 : : 86 : 0 : switch ( layer.valueSource ) 87 : : { 88 : : case ValueAttribute: 89 : : { 90 : 0 : QVariant attributeVariant = feature.attribute( layer.interpolationAttribute ); 91 : 0 : if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value) 92 : : { 93 : 0 : continue; 94 : : } 95 : 0 : attributeValue = attributeVariant.toDouble( &attributeConversionOk ); 96 : 0 : if ( !attributeConversionOk || std::isnan( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation 97 : : { 98 : 0 : continue; 99 : : } 100 : 0 : break; 101 : 0 : } 102 : : 103 : : case ValueZ: 104 : : case ValueM: 105 : 0 : break; 106 : : } 107 : : 108 : 0 : if ( !addVerticesToCache( feature.geometry(), layer.valueSource, attributeValue ) ) 109 : 0 : return FeatureGeometryError; 110 : : } 111 : 0 : layerCount++; 112 : 0 : } 113 : : 114 : 0 : return Success; 115 : 0 : } 116 : : 117 : 0 : bool QgsInterpolator::addVerticesToCache( const QgsGeometry &geom, ValueSource source, double attributeValue ) 118 : : { 119 : 0 : if ( geom.isNull() || geom.isEmpty() ) 120 : 0 : return true; // nothing to do 121 : : 122 : : //validate source 123 : 0 : switch ( source ) 124 : : { 125 : : case ValueAttribute: 126 : 0 : break; 127 : : 128 : : case ValueM: 129 : 0 : if ( !geom.constGet()->isMeasure() ) 130 : 0 : return false; 131 : : else 132 : 0 : break; 133 : : 134 : : case ValueZ: 135 : 0 : if ( !geom.constGet()->is3D() ) 136 : 0 : return false; 137 : : else 138 : 0 : break; 139 : : } 140 : : 141 : 0 : for ( auto point = geom.vertices_begin(); point != geom.vertices_end(); ++point ) 142 : : { 143 : 0 : switch ( source ) 144 : : { 145 : : case ValueM: 146 : 0 : mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).m() ) ); 147 : 0 : break; 148 : : 149 : : case ValueZ: 150 : 0 : mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).z() ) ); 151 : 0 : break; 152 : : 153 : : case ValueAttribute: 154 : 0 : mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), attributeValue ) ); 155 : 0 : break; 156 : : } 157 : 0 : } 158 : 0 : mDataIsCached = true; 159 : 0 : return true; 160 : 0 : }