1 /*************************************************************************** 2 qgsmeshcalcutils.h 3 ------------------ 4 begin : December 18th, 2018 5 copyright : (C) 2018 by Peter Petrik 6 email : zilolv 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 #ifndef QGSMESHCALCUTILS_H 19 #define QGSMESHCALCUTILS_H 20 21 #define SIP_NO_FILE 22 23 ///@cond PRIVATE 24 25 #include <QStringList> 26 #include <QMap> 27 #include <QVector> 28 29 #include <algorithm> 30 #include <functional> 31 #include <math.h> 32 #include <numeric> 33 34 #include "qgsrectangle.h" 35 #include "qgsmeshlayer.h" 36 #include "qgsmeshdataprovider.h" 37 #include "qgis_core.h" 38 39 /** 40 * \ingroup core 41 * \class QgsMeshCalcUtils 42 * \brief Mathematical operations on QgsMeshMemoryDatasetGroup 43 * 44 * QgsMeshMemoryDatasetGroups must be compatible (same mesh structure, same number of datasets, ...) 45 * Any operation with NODATA is NODATA (e.g. NODATA + 1 = NODATA) 46 * 47 * \since QGIS 3.6 48 */ 49 class CORE_EXPORT QgsMeshCalcUtils 50 { 51 public: 52 53 /** 54 * Creates the utils and validates the input 55 * 56 * The constructor fetches all dataset values and creates memory datasets from them. 57 * 58 * \param layer mesh layer 59 * \param usedGroupNames dataset group's names that are used in the expression 60 * \param startTime start time 61 * \param endTime end time 62 */ 63 QgsMeshCalcUtils( QgsMeshLayer *layer, 64 const QStringList &usedGroupNames, 65 double startTime, 66 double endTime ); 67 68 /** 69 * Creates the utils and validates the input 70 * 71 * The constructor fetches dataset values from selected dataset corresponding to the relative time \a relativeTime 72 * (see QgsMeshLayer::datasetIndexAtRelativeTime() and creates memory datasets from them. 73 * There are only one dataset per group, selected with the matching method defined for the layer. 74 * 75 * \param layer mesh layer 76 * \param usedGroupNames dataset group's names that are used in the expression 77 * \param timeRange time range 78 */ 79 QgsMeshCalcUtils( QgsMeshLayer *layer, 80 const QStringList &usedGroupNames, 81 const QgsInterval &relativeTime ); 82 83 //! Returns whether the input parameters are consistent and valid for given mesh layer 84 bool isValid() const; 85 86 //! Returns associated mesh layer 87 const QgsMeshLayer *layer() const; 88 89 //! Returns dataset group based on name 90 std::shared_ptr<const QgsMeshMemoryDatasetGroup> group( const QString &groupName ) const; 91 92 //! Creates a single dataset with all values set to 1 93 void ones( QgsMeshMemoryDatasetGroup &group1 ) const; 94 95 //! Creates a single dataset with all values set to NODATA 96 void nodata( QgsMeshMemoryDatasetGroup &group1 ) const; 97 98 //! Returns a single dataset with all values set to val 99 std::shared_ptr<QgsMeshMemoryDataset> number( double val, double time ) const; 100 101 //! Creates a deepcopy of group with groupName to group1. Does not copy datasets for filtered out times. 102 void copy( QgsMeshMemoryDatasetGroup &group1, const QString &groupName ) const; 103 104 //! Creates a deepcopy of dataset0 105 std::shared_ptr<QgsMeshMemoryDataset> copy( std::shared_ptr<const QgsMeshMemoryDataset> dataset0 ) const; 106 107 //! Changes ownership of all datasets from group2 to group1 108 void transferDatasets( QgsMeshMemoryDatasetGroup &group1, QgsMeshMemoryDatasetGroup &group2 ) const; 109 110 //! If group2 has more datasets than group1, duplicates datasets in group1 so it has the same number of datasets as group2 111 void expand( QgsMeshMemoryDatasetGroup &group1, 112 const QgsMeshMemoryDatasetGroup &group2 ) const; 113 114 //! Creates a single dataset with custom number 115 void number( QgsMeshMemoryDatasetGroup &group1, double val ) const; 116 117 //! If condition is TRUE (for given time&point), takes val from trueGroup else from falseGroup 118 void addIf( QgsMeshMemoryDatasetGroup &trueGroup, 119 const QgsMeshMemoryDatasetGroup &falseGroup, 120 const QgsMeshMemoryDatasetGroup &condition ) const; 121 122 //! Creates a spatial filter from extent 123 void filter( QgsMeshMemoryDatasetGroup &group1, const QgsRectangle &extent ) const; 124 125 //! Creates a spatial filter from geometry 126 void filter( QgsMeshMemoryDatasetGroup &group1, const QgsGeometry &mask ) const; 127 128 //! Operator NOT 129 void logicalNot( QgsMeshMemoryDatasetGroup &group1 ) const; 130 131 //! Operator SIGN 132 void changeSign( QgsMeshMemoryDatasetGroup &group1 ) const; 133 134 //! Operator ABS 135 void abs( QgsMeshMemoryDatasetGroup &group1 ) const; 136 137 //! Operator aggregated sum (over all datasets) 138 void sumAggregated( QgsMeshMemoryDatasetGroup &group1 ) const; 139 140 //! Operator aggregated min (over all datasets) 141 void minimumAggregated( QgsMeshMemoryDatasetGroup &group1 ) const; 142 143 //! Operator aggregated max (over all datasets) 144 void maximumAggregated( QgsMeshMemoryDatasetGroup &group1 ) const; 145 146 //! Operator aggregated average (over all datasets) 147 void averageAggregated( QgsMeshMemoryDatasetGroup &group1 ) const; 148 149 //! Operator + 150 void add( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 151 152 //! Operator - 153 void subtract( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 154 155 //! Operator * 156 void multiply( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 157 158 //! Operator / 159 void divide( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 160 161 //! Operator ^ 162 void power( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 163 164 //! Operator == 165 void equal( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 166 167 //! Operator != 168 void notEqual( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 169 170 //! Operator > 171 void greaterThan( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 172 173 //! Operator < 174 void lesserThan( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 175 176 //! Operator <= 177 void lesserEqual( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 178 179 //! Operator >= 180 void greaterEqual( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 181 182 //! Operator AND 183 void logicalAnd( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 184 185 //! Operator OR 186 void logicalOr( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 187 188 //! Operator minimum 189 void minimum( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 190 191 //! Operator maximum 192 void maximum( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 193 194 //! Calculates the data type of result dataset group 195 static QgsMeshDatasetGroupMetadata::DataType determineResultDataType( QgsMeshLayer *layer, const QStringList &usedGroupNames ); 196 197 //! Returns the data type of result dataset group 198 QgsMeshDatasetGroupMetadata::DataType outputType() const; 199 200 private: 201 double ffilter( double val1, double filter ) const; 202 double fadd( double val1, double val2 ) const; 203 double fsubtract( double val1, double val2 ) const; 204 double fmultiply( double val1, double val2 ) const; 205 double fdivide( double val1, double val2 ) const; 206 double fpower( double val1, double val2 ) const; 207 double fequal( double val1, double val2 ) const; 208 double fnotEqual( double val1, double val2 ) const; 209 double fgreaterThan( double val1, double val2 ) const; 210 double flesserThan( double val1, double val2 ) const; 211 double flesserEqual( double val1, double val2 ) const; 212 double fgreaterEqual( double val1, double val2 ) const; 213 double flogicalAnd( double val1, double val2 ) const; 214 double flogicalOr( double val1, double val2 ) const; 215 double flogicalNot( double val1 ) const; 216 double fchangeSign( double val1 ) const; 217 double fmin( double val1, double val2 ) const; 218 double fmax( double val1, double val2 ) const; 219 double fabs( double val1 ) const; 220 double fsumAggregated( QVector<double> &vals ) const; 221 double fminimumAggregated( QVector<double> &vals ) const; 222 double fmaximumAggregated( QVector<double> &vals ) const; 223 double faverageAggregated( QVector<double> &vals ) const; 224 225 /** 226 * Clones the dataset data to memory 227 * 228 * Finds dataset group in provider with the name and copies all values to 229 * memory dataset group. Returns NULLPTR if no such dataset group 230 * exists. Resulting datasets are guaranteed to have the same mOutputType type 231 */ 232 std::shared_ptr<QgsMeshMemoryDatasetGroup> createMemoryDatasetGroup( const QString &datasetGroupName, const QgsInterval &relativeTime = QgsInterval() ) const; 233 234 /** 235 * Creates dataset based on group. Initializes values and active based on group type. 236 */ 237 std::shared_ptr<QgsMeshMemoryDataset> createMemoryDataset( const QgsMeshMemoryDatasetGroup &grp ) const; 238 239 /** 240 * Creates dataset based on group. Fill with values of corresponding dataset 241 */ 242 std::shared_ptr<QgsMeshMemoryDataset> createMemoryDataset( const QgsMeshDatasetIndex &datasetIndex ) const; 243 244 /** 245 * Creates dataset with given type. Initializes values and active based on type. 246 */ 247 std::shared_ptr<QgsMeshMemoryDataset> createMemoryDataset( const QgsMeshDatasetGroupMetadata::DataType type ) const; 248 249 /** 250 * Returns dataset based on (time) index. If group has only 1 dataset, returns first one 251 */ 252 std::shared_ptr<QgsMeshMemoryDataset> canditateDataset( QgsMeshMemoryDatasetGroup &group, 253 int datasetIndex ) const; 254 255 /** 256 * Returns dataset based on on (time) index. If group has only 1 dataset, returns first one 257 */ 258 std::shared_ptr<const QgsMeshMemoryDataset> constCandidateDataset( const QgsMeshMemoryDatasetGroup &group, 259 int datasetIndex ) const; 260 261 /** 262 * Returns maximum number of datasets in the groups 263 */ 264 int datasetCount( const QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const; 265 266 /** 267 * Set active property for vertices in dataset based on: 268 * if given vertex is active in dataset and refDataset 269 * if all values in vertices that are referenced by the dataset are not NODATA 270 */ 271 void activate( std::shared_ptr<QgsMeshMemoryDataset> dataset, 272 std::shared_ptr<const QgsMeshMemoryDataset> refDataset = nullptr ) const; 273 274 //! Activates all datasets in group 275 void activate( QgsMeshMemoryDatasetGroup &group ) const; 276 277 //! Creates spatial filter group from rectagle 278 void populateSpatialFilter( QgsMeshMemoryDatasetGroup &filter, const QgsRectangle &extent ) const; // create a filter from extent 279 280 //! Creates mask filter group from geometry 281 void populateMaskFilter( QgsMeshMemoryDatasetGroup &filter, const QgsGeometry &mask ) const; // create a filter from mask 282 283 //! Calculates unary operators 284 void func1( QgsMeshMemoryDatasetGroup &group, 285 std::function<double( double )> func ) const; 286 287 //! Calculates binary operators 288 void func2( QgsMeshMemoryDatasetGroup &group1, 289 const QgsMeshMemoryDatasetGroup &group2, 290 std::function<double( double, double )> func ) const; 291 292 //! Calculates unary aggregate operator (e.g. sum of values of one vertex for all times) 293 void funcAggr( QgsMeshMemoryDatasetGroup &group1, 294 std::function<double( QVector<double>& )> func ) const; 295 296 const QgsTriangularMesh *triangularMesh() const; 297 const QgsMesh *nativeMesh() const; 298 void updateMesh() const; 299 300 QgsMeshLayer *mMeshLayer; //!< Reference mesh 301 bool mIsValid; //!< All used datasets (in datasetMap) do have outputs for same times & all used dataset names are present in mesh 302 QgsMeshDatasetGroupMetadata::DataType mOutputType; //!< Mesh can work only with one output types, so you cannot mix 303 //!< E.g. one dataset with element outputs and one with node outputs 304 QVector<double> mTimes; 305 QMap < QString, std::shared_ptr<QgsMeshMemoryDatasetGroup> > mDatasetGroupMap; //!< Groups that are referenced in the expression 306 }; 307 308 ///@endcond 309 310 #endif // QGSMESHCALCUTILS_H 311