1 /*************************************************************************** 2 qgspropertytransformer.h 3 ------------------------ 4 Date : January 2017 5 Copyright : (C) 2017 by Nyall Dawson 6 Email : nyall dot dawson at gmail dot com 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 #ifndef QGSPROPERTYTRANSFORMER_H 16 #define QGSPROPERTYTRANSFORMER_H 17 18 #include "qgis_core.h" 19 #include "qgsexpression.h" 20 #include "qgsexpressioncontext.h" 21 #include "qgspointxy.h" 22 #include <QVariant> 23 #include <QHash> 24 #include <QString> 25 #include <QStringList> 26 #include <QDomElement> 27 #include <QDomDocument> 28 #include <QColor> 29 #include <memory> 30 #include <algorithm> 31 32 class QgsColorRamp; 33 34 35 /** 36 * \ingroup core 37 * \class QgsCurveTransform 38 * \brief Handles scaling of input values to output values by using a curve created 39 * from smoothly joining a number of set control points. 40 * 41 * QgsCurveTransform assists in creation of curve type transforms, typically seen in 42 * raster image editing software (eg the curves dialog in GIMP or Photoshop). 43 * Transforms are created by passing a number of set control points through which 44 * the transform curve must pass. The curve is guaranteed to exactly pass through 45 * these control points. Between control points the curve is smoothly interpolated 46 * so that no disjoint sections or "corners" are present. 47 * 48 * If the first or last control point are not located at x = 0 and x = 1 respectively, 49 * then values outside this range will be mapped to the y value of either the first 50 * or last control point. In other words, the curve will have a flat segment 51 * for values outside of the control point range. 52 * 53 * \since QGIS 3.0 54 */ 55 56 class CORE_EXPORT QgsCurveTransform 57 { 58 public: 59 60 /** 61 * Constructs a default QgsCurveTransform which linearly maps values 62 * between 0 and 1 unchanged. I.e. y == x. 63 */ 64 QgsCurveTransform(); 65 66 /** 67 * Constructs a QgsCurveTransform using a specified list of \a controlPoints. 68 * Behavior is undefined if duplicate x values exist in the control points 69 * list. 70 */ 71 QgsCurveTransform( const QList< QgsPointXY > &controlPoints ); 72 73 ~QgsCurveTransform(); 74 75 /** 76 * Copy constructor 77 */ 78 QgsCurveTransform( const QgsCurveTransform &other ); 79 80 QgsCurveTransform &operator=( const QgsCurveTransform &other ); 81 82 /** 83 * Returns a list of the control points for the transform. 84 * \see setControlPoints() 85 */ controlPoints()86 QList< QgsPointXY > controlPoints() const { return mControlPoints; } 87 88 /** 89 * Sets the list of control points for the transform. Any existing 90 * points are removed. 91 * \see controlPoints() 92 */ 93 void setControlPoints( const QList< QgsPointXY > &points ); 94 95 /** 96 * Adds a control point to the transform. Behavior is undefined if duplicate 97 * x values exist in the control points list. 98 * \see removeControlPoint() 99 */ 100 void addControlPoint( double x, double y ); 101 102 /** 103 * Removes a control point from the transform. This will have no effect if a 104 * matching control point does not exist. 105 * \see addControlPoint() 106 */ 107 void removeControlPoint( double x, double y ); 108 109 /** 110 * Returns the mapped y value corresponding to the specified \a x value. 111 */ 112 double y( double x ) const; 113 114 /** 115 * Returns a list of y values corresponding to a list of \a x values. 116 * Calling this method is faster then calling the double variant multiple 117 * times. 118 */ 119 QVector< double > y( const QVector< double > &x ) const; 120 121 /** 122 * Reads the curve's state from an XML element. 123 * \param elem source DOM element for transform's state 124 * \param doc DOM document 125 * \see writeXml() 126 */ 127 bool readXml( const QDomElement &elem, const QDomDocument &doc ); 128 129 /** 130 * Writes the current state of the transform into an XML element 131 * \param transformElem destination element for the transform's state 132 * \param doc DOM document 133 * \see readXml() 134 */ 135 bool writeXml( QDomElement &transformElem, QDomDocument &doc ) const; 136 137 /** 138 * Saves this curve transformer to a QVariantMap, wrapped in a QVariant. 139 * You can use QgsXmlUtils::writeVariant to save it to an XML document. 140 * 141 * \see loadVariant() 142 */ 143 QVariant toVariant() const; 144 145 /** 146 * Load this curve transformer from a QVariantMap, wrapped in a QVariant. 147 * You can use QgsXmlUtils::writeVariant to load it from an XML document. 148 * 149 * \see toVariant() 150 */ 151 bool loadVariant( const QVariant &transformer ); 152 153 private: 154 155 void calcSecondDerivativeArray(); 156 157 QList< QgsPointXY > mControlPoints; 158 159 double *mSecondDerivativeArray = nullptr; 160 }; 161 162 163 /** 164 * \ingroup core 165 * \class QgsPropertyTransformer 166 * \brief Abstract base class for objects which transform the calculated value of a property. 167 * Possible uses include transformers which map a value into a scaled size or color from a gradient. 168 * \since QGIS 3.0 169 */ 170 class CORE_EXPORT QgsPropertyTransformer 171 { 172 173 #ifdef SIP_RUN 174 SIP_CONVERT_TO_SUBCLASS_CODE 175 if ( sipCpp->transformerType() == QgsPropertyTransformer::GenericNumericTransformer ) 176 sipType = sipType_QgsGenericNumericTransformer; 177 else if ( sipCpp->transformerType() == QgsPropertyTransformer::SizeScaleTransformer ) 178 sipType = sipType_QgsSizeScaleTransformer; 179 else if ( sipCpp->transformerType() == QgsPropertyTransformer::ColorRampTransformer ) 180 sipType = sipType_QgsColorRampTransformer; 181 else 182 sipType = sipType_QgsPropertyTransformer; 183 SIP_END 184 #endif 185 186 public: 187 188 //! Transformer types 189 enum Type 190 { 191 GenericNumericTransformer, //!< Generic transformer for numeric values (QgsGenericNumericTransformer) 192 SizeScaleTransformer, //!< Size scaling transformer (QgsSizeScaleTransformer) 193 ColorRampTransformer, //!< Color ramp transformer (QgsColorRampTransformer) 194 }; 195 196 /** 197 * Factory method for creating a new property transformer of the specified type. 198 * \param type transformer type to create 199 */ 200 static QgsPropertyTransformer *create( Type type ) SIP_FACTORY; 201 202 /** 203 * Constructor for QgsPropertyTransformer 204 * \param minValue minimum expected value from source property 205 * \param maxValue maximum expected value from source property 206 */ 207 QgsPropertyTransformer( double minValue = 0.0, double maxValue = 1.0 ); 208 209 /** 210 * Copy constructor. 211 */ 212 QgsPropertyTransformer( const QgsPropertyTransformer &other ); 213 QgsPropertyTransformer &operator=( const QgsPropertyTransformer &other ); 214 215 virtual ~QgsPropertyTransformer(); 216 217 /** 218 * Returns the transformer type. 219 */ 220 virtual Type transformerType() const = 0; 221 222 /** 223 * Returns a clone of the transformer. 224 */ 225 virtual QgsPropertyTransformer *clone() const = 0 SIP_FACTORY; 226 227 /** 228 * Loads this transformer from a QVariantMap, wrapped in a QVariant. 229 * You can use QgsXmlUtils::readVariant to read it from an XML document. 230 * 231 * \see toVariant() 232 */ 233 virtual bool loadVariant( const QVariant &transformer ); 234 235 /** 236 * Saves this transformer to a QVariantMap, wrapped in a QVariant. 237 * You can use QgsXmlUtils::writeVariant to save it to an XML document. 238 * 239 * \see loadVariant() 240 */ 241 virtual QVariant toVariant() const; 242 243 /** 244 * Returns the minimum value expected by the transformer. 245 * \see maxValue() 246 * \see setMinValue() 247 */ minValue()248 double minValue() const { return mMinValue; } 249 250 /** 251 * Sets the minimum value expected by the transformer. 252 * \param min minimum value 253 * \see setMaxValue() 254 * \see minValue() 255 */ setMinValue(double min)256 void setMinValue( double min ) { mMinValue = min; } 257 258 /** 259 * Returns the maximum value expected by the transformer. 260 * \see minValue() 261 * \see setMaxValue() 262 */ maxValue()263 double maxValue() const { return mMaxValue; } 264 265 /** 266 * Sets the maximum value expected by the transformer. 267 * \param max maximum value 268 * \see setMinValue() 269 * \see maxValue() 270 */ setMaxValue(double max)271 void setMaxValue( double max ) { mMaxValue = max; } 272 273 /** 274 * Returns the curve transform applied to input values before they are transformed 275 * by the individual transform subclasses. 276 * \see setCurveTransform() 277 */ curveTransform()278 QgsCurveTransform *curveTransform() const { return mCurveTransform.get(); } 279 280 /** 281 * Sets a curve transform to apply to input values before they are transformed 282 * by the individual transform subclasses. Ownership of \a transform is transferred 283 * to the property transformer. 284 * \see curveTransform() 285 */ setCurveTransform(QgsCurveTransform * transform SIP_TRANSFER)286 void setCurveTransform( QgsCurveTransform *transform SIP_TRANSFER ) { mCurveTransform.reset( transform ); } 287 288 /** 289 * Calculates the transform of a value. Derived classes must implement this to perform their transformations 290 * on input values 291 * \param context expression context 292 * \param value input value to transform 293 */ 294 virtual QVariant transform( const QgsExpressionContext &context, const QVariant &value ) const = 0; 295 296 /** 297 * Converts the transformer to a QGIS expression string. The \a baseExpression string consists 298 * of a sub-expression reflecting the parent property's state. 299 */ 300 virtual QString toExpression( const QString &baseExpression ) const = 0; 301 302 /** 303 * Attempts to parse an expression into a corresponding property transformer. 304 * \param expression expression to parse 305 * \param baseExpression will be set to the component of the source expression which 306 * is used to calculate the input to the property transformer. This will be set to an 307 * empty string if a field reference is the transformer input. 308 * \param fieldName will be set to a field name which is used to calculate the input 309 * to the property transformer. This will be set to an 310 * empty string if an expression is the transformer input. 311 * \returns corresponding property transformer, or NULLPTR if expression could not 312 * be parsed to a transformer. 313 */ 314 static QgsPropertyTransformer *fromExpression( const QString &expression, QString &baseExpression SIP_OUT, QString &fieldName SIP_OUT ) SIP_FACTORY; 315 316 protected: 317 318 /** 319 * Applies base class numeric transformations. Derived classes should call this 320 * to transform an \a input numeric value before they apply any transform to the result. 321 * This applies any curve transforms which may exist on the transformer. 322 */ 323 double transformNumeric( double input ) const; 324 #ifndef SIP_RUN 325 //! Minimum value expected by the transformer 326 double mMinValue; 327 328 //! Maximum value expected by the transformer 329 double mMaxValue; 330 331 //! Optional curve transform 332 std::unique_ptr< QgsCurveTransform > mCurveTransform; 333 #endif 334 }; 335 336 /** 337 * \ingroup core 338 * \class QgsGenericNumericTransformer 339 * \brief QgsPropertyTransformer subclass for scaling an input numeric value into an output numeric value. 340 * \since QGIS 3.0 341 */ 342 343 class CORE_EXPORT QgsGenericNumericTransformer : public QgsPropertyTransformer 344 { 345 public: 346 347 /** 348 * Constructor for QgsGenericNumericTransformer. 349 * \param minValue minimum expected input value 350 * \param maxValue maximum expected input value 351 * \param minOutput minimum value to return 352 * \param maxOutput maximum value to return 353 * \param nullOutput value to return for null inputs 354 * \param exponent optional exponential for non-linear scaling 355 */ 356 QgsGenericNumericTransformer( double minValue = 0.0, 357 double maxValue = 1.0, 358 double minOutput = 0.0, 359 double maxOutput = 1.0, 360 double nullOutput = 0.0, 361 double exponent = 1.0 ); 362 transformerType()363 Type transformerType() const override { return GenericNumericTransformer; } 364 QgsGenericNumericTransformer *clone() const override SIP_FACTORY; 365 QVariant toVariant() const override; 366 bool loadVariant( const QVariant &definition ) override; 367 QVariant transform( const QgsExpressionContext &context, const QVariant &value ) const override; 368 QString toExpression( const QString &baseExpression ) const override; 369 370 /** 371 * Attempts to parse an expression into a corresponding QgsSizeScaleTransformer. 372 * \param expression expression to parse 373 * \param baseExpression will be set to the component of the source expression which 374 * is used to calculate the input to the property transformer. This will be set to an 375 * empty string if a field reference is the transformer input. 376 * \param fieldName will be set to a field name which is used to calculate the input 377 * to the property transformer. This will be set to an 378 * empty string if an expression is the transformer input. 379 * \returns corresponding QgsSizeScaleTransformer, or NULLPTR if expression could not 380 * be parsed to a size scale transformer. 381 */ 382 static QgsGenericNumericTransformer *fromExpression( const QString &expression, QString &baseExpression SIP_OUT, QString &fieldName SIP_OUT ) SIP_FACTORY; 383 384 /** 385 * Calculates the size corresponding to a specific \a input value. 386 * \returns calculated size using size scale transformer's parameters and type 387 */ 388 double value( double input ) const; 389 390 /** 391 * Returns the minimum calculated size. 392 * \see setMinOutputValue() 393 * \see maxOutputValue() 394 */ minOutputValue()395 double minOutputValue() const { return mMinOutput; } 396 397 /** 398 * Sets the minimum calculated size. 399 * \param size minimum size 400 * \see minOutputValue() 401 * \see setMaxOutputValue() 402 */ setMinOutputValue(double size)403 void setMinOutputValue( double size ) { mMinOutput = size; } 404 405 /** 406 * Returns the maximum calculated size. 407 * \see minOutputValue() 408 */ maxOutputValue()409 double maxOutputValue() const { return mMaxOutput; } 410 411 /** 412 * Sets the maximum calculated size. 413 * \param size maximum size 414 * \see maxOutputValue() 415 * \see setMinOutputValue() 416 */ setMaxOutputValue(double size)417 void setMaxOutputValue( double size ) { mMaxOutput = size; } 418 419 /** 420 * Returns the size value when an expression evaluates to NULL. 421 * \see setNullOutputValue() 422 */ nullOutputValue()423 double nullOutputValue() const { return mNullOutput; } 424 425 /** 426 * Sets the size value for when an expression evaluates to NULL. 427 * \param size null size 428 * \see nullOutputValue() 429 */ setNullOutputValue(double size)430 void setNullOutputValue( double size ) { mNullOutput = size; } 431 432 /** 433 * Returns the exponent for an exponential expression. 434 * \see setExponent() 435 */ exponent()436 double exponent() const { return mExponent; } 437 438 /** 439 * Sets the exponent for an exponential expression. 440 * \param exponent exponent 441 * \see exponent() 442 */ setExponent(double exponent)443 void setExponent( double exponent ) { mExponent = exponent; } 444 445 private: 446 double mMinOutput; 447 double mMaxOutput; 448 double mNullOutput; 449 double mExponent; 450 451 }; 452 453 /** 454 * \ingroup core 455 * \class QgsSizeScaleTransformer 456 * \brief QgsPropertyTransformer subclass for scaling a value into a size according to various 457 * scaling methods. 458 * \since QGIS 3.0 459 */ 460 461 class CORE_EXPORT QgsSizeScaleTransformer : public QgsPropertyTransformer 462 { 463 public: 464 465 //! Size scaling methods 466 enum ScaleType 467 { 468 Linear, //!< Linear scaling 469 Area, //!< Area based scaling 470 Flannery, //!< Flannery scaling method 471 Exponential, //!< Scale using set exponent 472 }; 473 474 /** 475 * Constructor for QgsSizeScaleTransformer. 476 * \param type scaling type 477 * \param minValue minimum expected value 478 * \param maxValue maximum expected value 479 * \param minSize minimum size to return 480 * \param maxSize maximum size to return 481 * \param nullSize size to return for null values 482 * \param exponent exponent for Exponential scaling method 483 */ 484 QgsSizeScaleTransformer( ScaleType type = Linear, 485 double minValue = 0.0, 486 double maxValue = 1.0, 487 double minSize = 0.0, 488 double maxSize = 1.0, 489 double nullSize = 0.0, 490 double exponent = 1.0 ); 491 transformerType()492 Type transformerType() const override { return SizeScaleTransformer; } 493 QgsSizeScaleTransformer *clone() const override SIP_FACTORY; 494 QVariant toVariant() const override; 495 bool loadVariant( const QVariant &definition ) override; 496 QVariant transform( const QgsExpressionContext &context, const QVariant &value ) const override; 497 QString toExpression( const QString &baseExpression ) const override; 498 499 /** 500 * Attempts to parse an expression into a corresponding QgsSizeScaleTransformer. 501 * \param expression expression to parse 502 * \param baseExpression will be set to the component of the source expression which 503 * is used to calculate the input to the property transformer. This will be set to an 504 * empty string if a field reference is the transformer input. 505 * \param fieldName will be set to a field name which is used to calculate the input 506 * to the property transformer. This will be set to an 507 * empty string if an expression is the transformer input. 508 * \returns corresponding QgsSizeScaleTransformer, or NULLPTR if expression could not 509 * be parsed to a size scale transformer. 510 */ 511 static QgsSizeScaleTransformer *fromExpression( const QString &expression, QString &baseExpression SIP_OUT, QString &fieldName SIP_OUT ) SIP_FACTORY; 512 513 /** 514 * Calculates the size corresponding to a specific value. 515 * \param value value to calculate size for 516 * \returns calculated size using size scale transformer's parameters and type 517 */ 518 double size( double value ) const; 519 520 /** 521 * Returns the minimum calculated size. 522 * \see setMinSize() 523 * \see maxSize() 524 */ minSize()525 double minSize() const { return mMinSize; } 526 527 /** 528 * Sets the minimum calculated size. 529 * \param size minimum size 530 * \see minSize() 531 * \see setMaxSize() 532 */ setMinSize(double size)533 void setMinSize( double size ) { mMinSize = size; } 534 535 /** 536 * Returns the maximum calculated size. 537 * \see minSize() 538 */ maxSize()539 double maxSize() const { return mMaxSize; } 540 541 /** 542 * Sets the maximum calculated size. 543 * \param size maximum size 544 * \see maxSize() 545 * \see setMinSize() 546 */ setMaxSize(double size)547 void setMaxSize( double size ) { mMaxSize = size; } 548 549 /** 550 * Returns the size value when an expression evaluates to NULL. 551 * \see setNullSize() 552 */ nullSize()553 double nullSize() const { return mNullSize; } 554 555 /** 556 * Sets the size value for when an expression evaluates to NULL. 557 * \param size null size 558 * \see nullSize() 559 */ setNullSize(double size)560 void setNullSize( double size ) { mNullSize = size; } 561 562 /** 563 * Returns the exponent for an exponential expression. 564 * \see setExponent() 565 * \see type() 566 */ exponent()567 double exponent() const { return mExponent; } 568 569 /** 570 * Sets the exponent for an exponential expression. 571 * \param exponent exponent 572 * \see exponent() 573 */ setExponent(double exponent)574 void setExponent( double exponent ) { mExponent = exponent; } 575 576 /** 577 * Returns the size transformer's scaling type (the method used to calculate 578 * the size from a value). 579 * \see setType() 580 */ type()581 ScaleType type() const { return mType; } 582 583 /** 584 * Sets the size transformer's scaling type (the method used to calculate 585 * the size from a value). 586 * \param type scale type 587 * \see type() 588 */ 589 void setType( ScaleType type ); 590 591 private: 592 ScaleType mType = Linear; 593 double mMinSize; 594 double mMaxSize; 595 double mNullSize; 596 double mExponent; 597 598 }; 599 600 /** 601 * \ingroup core 602 * \class QgsColorRampTransformer 603 * \brief QgsPropertyTransformer subclass for transforming a numeric value into a color from a 604 * color ramp. 605 * \since QGIS 3.0 606 */ 607 608 class CORE_EXPORT QgsColorRampTransformer : public QgsPropertyTransformer 609 { 610 public: 611 612 /** 613 * Constructor for QgsColorRampTransformer. 614 * \param minValue minimum expected value 615 * \param maxValue maximum expected value 616 * \param ramp source color ramp. Ownership is transferred to the transformer. 617 * \param nullColor color to return for null values 618 */ 619 QgsColorRampTransformer( double minValue = 0.0, 620 double maxValue = 1.0, 621 QgsColorRamp *ramp SIP_TRANSFER = nullptr, 622 const QColor &nullColor = QColor( 0, 0, 0, 0 ) ); 623 624 //! Copy constructor 625 QgsColorRampTransformer( const QgsColorRampTransformer &other ); 626 627 QgsColorRampTransformer &operator=( const QgsColorRampTransformer &other ); 628 transformerType()629 Type transformerType() const override { return ColorRampTransformer; } 630 QgsColorRampTransformer *clone() const override SIP_FACTORY; 631 QVariant toVariant() const override; 632 bool loadVariant( const QVariant &definition ) override; 633 QVariant transform( const QgsExpressionContext &context, const QVariant &value ) const override; 634 QString toExpression( const QString &baseExpression ) const override; 635 636 /** 637 * Calculates the color corresponding to a specific value. 638 * \param value value to calculate color for 639 * \returns calculated color using transformer's parameters and type 640 */ 641 QColor color( double value ) const; 642 643 /** 644 * Returns the color ramp used for calculating property colors. 645 * \returns color ramp 646 * \see setColorRamp() 647 */ 648 QgsColorRamp *colorRamp() const; 649 650 /** 651 * Sets the color ramp to use for calculating property colors. 652 * \param ramp color ramp, ownership of ramp is transferred to the transformer. 653 * \see colorRamp() 654 */ 655 void setColorRamp( QgsColorRamp *ramp SIP_TRANSFER ); 656 657 /** 658 * Returns the color corresponding to a null value. 659 * \see setNullColor() 660 */ nullColor()661 QColor nullColor() const { return mNullColor; } 662 663 /** 664 * Sets the color corresponding to a null value. 665 * \param color null color 666 * \see nullColor() 667 */ setNullColor(const QColor & color)668 void setNullColor( const QColor &color ) { mNullColor = color; } 669 670 /** 671 * Returns the color ramp's name. 672 * \see setRampName() 673 */ rampName()674 QString rampName() const { return mRampName; } 675 676 /** 677 * Sets the color ramp's \a name. The ramp name must be set to match 678 * a color ramp available in the style database for conversion to expression 679 * to work correctly. 680 * \see rampName() 681 */ setRampName(const QString & name)682 void setRampName( const QString &name ) { mRampName = name; } 683 684 private: 685 686 std::unique_ptr< QgsColorRamp > mGradientRamp; 687 QColor mNullColor; 688 QString mRampName; 689 690 }; 691 692 #endif // QGSPROPERTYTRANSFORMER_H 693