QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgspropertytransformer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspropertytransformer.cpp
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 
16 #include "qgspropertytransformer.h"
17 
18 #include "qgslogger.h"
19 #include "qgsexpression.h"
20 #include "qgsexpressionnodeimpl.h"
21 #include "qgssymbollayerutils.h"
22 #include "qgscolorramp.h"
23 #include "qgspointxy.h"
24 
25 
26 //
27 // QgsPropertyTransformer
28 //
29 
31 {
32  QgsPropertyTransformer *transformer = nullptr;
33  switch ( type )
34  {
36  transformer = new QgsGenericNumericTransformer();
37  break;
39  transformer = new QgsSizeScaleTransformer();
40  break;
42  transformer = new QgsColorRampTransformer();
43  break;
44  }
45  return transformer;
46 }
47 
48 QgsPropertyTransformer::QgsPropertyTransformer( double minValue, double maxValue )
49  : mMinValue( minValue )
50  , mMaxValue( maxValue )
51 {}
52 
54  : mMinValue( other.mMinValue )
55  , mMaxValue( other.mMaxValue )
56  , mCurveTransform( other.mCurveTransform ? new QgsCurveTransform( *other.mCurveTransform ) : nullptr )
57 {}
58 
60 {
61  mMinValue = other.mMinValue;
62  mMaxValue = other.mMaxValue;
63  mCurveTransform.reset( other.mCurveTransform ? new QgsCurveTransform( *other.mCurveTransform ) : nullptr );
64  return *this;
65 }
66 
68 
69 bool QgsPropertyTransformer::loadVariant( const QVariant &transformer )
70 {
71  QVariantMap transformerMap = transformer.toMap();
72 
73  mMinValue = transformerMap.value( QStringLiteral( "minValue" ), 0.0 ).toDouble();
74  mMaxValue = transformerMap.value( QStringLiteral( "maxValue" ), 1.0 ).toDouble();
75  mCurveTransform.reset( nullptr );
76 
77  QVariantMap curve = transformerMap.value( QStringLiteral( "curve" ) ).toMap();
78 
79  if ( !curve.isEmpty() )
80  {
81  mCurveTransform.reset( new QgsCurveTransform() );
82  mCurveTransform->loadVariant( curve );
83  }
84 
85  return true;
86 }
87 
89 {
90  QVariantMap transformerMap;
91 
92  transformerMap.insert( QStringLiteral( "minValue" ), mMinValue );
93  transformerMap.insert( QStringLiteral( "maxValue" ), mMaxValue );
94 
95  if ( mCurveTransform )
96  {
97  transformerMap.insert( QStringLiteral( "curve" ), mCurveTransform->toVariant() );
98  }
99  return transformerMap;
100 }
101 
102 QgsPropertyTransformer *QgsPropertyTransformer::fromExpression( const QString &expression, QString &baseExpression, QString &fieldName )
103 {
104  baseExpression.clear();
105  fieldName.clear();
106 
107  if ( QgsPropertyTransformer *sizeScale = QgsSizeScaleTransformer::fromExpression( expression, baseExpression, fieldName ) )
108  return sizeScale;
109  else
110  return nullptr;
111 }
112 
113 double QgsPropertyTransformer::transformNumeric( double input ) const
114 {
115  if ( !mCurveTransform )
116  return input;
117 
119  return input;
120 
121  // convert input into target range
122  double scaledInput = ( input - mMinValue ) / ( mMaxValue - mMinValue );
123 
124  return mMinValue + ( mMaxValue - mMinValue ) * mCurveTransform->y( scaledInput );
125 }
126 
127 
128 //
129 // QgsGenericNumericTransformer
130 //
131 
132 QgsGenericNumericTransformer::QgsGenericNumericTransformer( double minValue, double maxValue, double minOutput, double maxOutput, double nullOutput, double exponent )
133  : QgsPropertyTransformer( minValue, maxValue )
134  , mMinOutput( minOutput )
135  , mMaxOutput( maxOutput )
136  , mNullOutput( nullOutput )
137  , mExponent( exponent )
138 {}
139 
141 {
142  std::unique_ptr< QgsGenericNumericTransformer > t( new QgsGenericNumericTransformer( mMinValue,
143  mMaxValue,
144  mMinOutput,
145  mMaxOutput,
146  mNullOutput,
147  mExponent ) );
148  if ( mCurveTransform )
149  t->setCurveTransform( new QgsCurveTransform( *mCurveTransform ) );
150  return t.release();
151 }
152 
154 {
155  QVariantMap transformerMap = QgsPropertyTransformer::toVariant().toMap();
156 
157  transformerMap.insert( QStringLiteral( "minOutput" ), mMinOutput );
158  transformerMap.insert( QStringLiteral( "maxOutput" ), mMaxOutput );
159  transformerMap.insert( QStringLiteral( "nullOutput" ), mNullOutput );
160  transformerMap.insert( QStringLiteral( "exponent" ), mExponent );
161 
162  return transformerMap;
163 }
164 
165 bool QgsGenericNumericTransformer::loadVariant( const QVariant &transformer )
166 {
168 
169  QVariantMap transformerMap = transformer.toMap();
170 
171  mMinOutput = transformerMap.value( QStringLiteral( "minOutput" ), 0.0 ).toDouble();
172  mMaxOutput = transformerMap.value( QStringLiteral( "maxOutput" ), 1.0 ).toDouble();
173  mNullOutput = transformerMap.value( QStringLiteral( "nullOutput" ), 0.0 ).toDouble();
174  mExponent = transformerMap.value( QStringLiteral( "exponent" ), 1.0 ).toDouble();
175  return true;
176 }
177 
178 double QgsGenericNumericTransformer::value( double input ) const
179 {
181  return qBound( mMinOutput, input, mMaxOutput );
182 
183  input = transformNumeric( input );
184  if ( qgsDoubleNear( mExponent, 1.0 ) )
185  return mMinOutput + ( qBound( mMinValue, input, mMaxValue ) - mMinValue ) * ( mMaxOutput - mMinOutput ) / ( mMaxValue - mMinValue );
186  else
187  return mMinOutput + std::pow( qBound( mMinValue, input, mMaxValue ) - mMinValue, mExponent ) * ( mMaxOutput - mMinOutput ) / std::pow( mMaxValue - mMinValue, mExponent );
188 }
189 
190 QVariant QgsGenericNumericTransformer::transform( const QgsExpressionContext &context, const QVariant &v ) const
191 {
192  Q_UNUSED( context )
193 
194  if ( v.isNull() )
195  return mNullOutput;
196 
197  bool ok;
198  double dblValue = v.toDouble( &ok );
199 
200  if ( ok )
201  {
202  //apply scaling to value
203  return value( dblValue );
204  }
205  else
206  {
207  return v;
208  }
209 }
210 
211 QString QgsGenericNumericTransformer::toExpression( const QString &baseExpression ) const
212 {
213  QString minValueString = QString::number( mMinValue );
214  QString maxValueString = QString::number( mMaxValue );
215  QString minOutputString = QString::number( mMinOutput );
216  QString maxOutputString = QString::number( mMaxOutput );
217  QString nullOutputString = QString::number( mNullOutput );
218  QString exponentString = QString::number( mExponent );
219 
220  if ( qgsDoubleNear( mExponent, 1.0 ) )
221  return QStringLiteral( "coalesce(scale_linear(%1, %2, %3, %4, %5), %6)" ).arg( baseExpression, minValueString, maxValueString, minOutputString, maxOutputString, nullOutputString );
222  else
223  return QStringLiteral( "coalesce(scale_exp(%1, %2, %3, %4, %5, %6), %7)" ).arg( baseExpression, minValueString, maxValueString, minOutputString, maxOutputString, exponentString, nullOutputString );
224 }
225 
226 QgsGenericNumericTransformer *QgsGenericNumericTransformer::fromExpression( const QString &expression, QString &baseExpression, QString &fieldName )
227 {
228  bool ok = false;
229 
230  double nullValue = 0.0;
231  double exponent = 1.0;
232 
233  baseExpression.clear();
234  fieldName.clear();
235 
236  QgsExpression e( expression );
237 
238  if ( !e.rootNode() )
239  return nullptr;
240 
241  const QgsExpressionNodeFunction *f = dynamic_cast<const QgsExpressionNodeFunction *>( e.rootNode() );
242  if ( !f )
243  return nullptr;
244 
245  QList<QgsExpressionNode *> args = f->args()->list();
246 
247  // the scale function may be enclosed in a coalesce(expr, 0) to avoid NULL value
248  // to be drawn with the default size
249  if ( "coalesce" == QgsExpression::Functions()[f->fnIndex()]->name() )
250  {
251  f = dynamic_cast<const QgsExpressionNodeFunction *>( args[0] );
252  if ( !f )
253  return nullptr;
254  nullValue = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
255  if ( ! ok )
256  return nullptr;
257  args = f->args()->list();
258  }
259 
260  if ( "scale_linear" == QgsExpression::Functions()[f->fnIndex()]->name() )
261  {
262  exponent = 1.0;
263  }
264  else if ( "scale_exp" == QgsExpression::Functions()[f->fnIndex()]->name() )
265  {
266  exponent = QgsExpression( args[5]->dump() ).evaluate().toDouble( &ok );
267  }
268  else
269  {
270  return nullptr;
271  }
272 
273  bool expOk = true;
274  double minValue = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
275  expOk &= ok;
276  double maxValue = QgsExpression( args[2]->dump() ).evaluate().toDouble( &ok );
277  expOk &= ok;
278  double minOutput = QgsExpression( args[3]->dump() ).evaluate().toDouble( &ok );
279  expOk &= ok;
280  double maxOutput = QgsExpression( args[4]->dump() ).evaluate().toDouble( &ok );
281  expOk &= ok;
282 
283  if ( !expOk )
284  {
285  return nullptr;
286  }
287 
288  if ( args[0]->nodeType() == QgsExpressionNode::ntColumnRef )
289  {
290  fieldName = static_cast< QgsExpressionNodeColumnRef * >( args[0] )->name();
291  }
292  else
293  {
294  baseExpression = args[0]->dump();
295  }
296  return new QgsGenericNumericTransformer( minValue, maxValue, minOutput, maxOutput, nullValue, exponent );
297 }
298 
299 
300 
301 //
302 // QgsSizeScaleProperty
303 //
304 QgsSizeScaleTransformer::QgsSizeScaleTransformer( ScaleType type, double minValue, double maxValue, double minSize, double maxSize, double nullSize, double exponent )
305  : QgsPropertyTransformer( minValue, maxValue )
306  , mMinSize( minSize )
307  , mMaxSize( maxSize )
308  , mNullSize( nullSize )
309  , mExponent( exponent )
310 {
311  setType( type );
312 }
313 
315 {
316  std::unique_ptr< QgsSizeScaleTransformer > t( new QgsSizeScaleTransformer( mType,
317  mMinValue,
318  mMaxValue,
319  mMinSize,
320  mMaxSize,
321  mNullSize,
322  mExponent ) );
323  if ( mCurveTransform )
324  t->setCurveTransform( new QgsCurveTransform( *mCurveTransform ) );
325  return t.release();
326 }
327 
329 {
330  QVariantMap transformerMap = QgsPropertyTransformer::toVariant().toMap();
331 
332  transformerMap.insert( QStringLiteral( "scaleType" ), static_cast< int >( mType ) );
333  transformerMap.insert( QStringLiteral( "minSize" ), mMinSize );
334  transformerMap.insert( QStringLiteral( "maxSize" ), mMaxSize );
335  transformerMap.insert( QStringLiteral( "nullSize" ), mNullSize );
336  transformerMap.insert( QStringLiteral( "exponent" ), mExponent );
337 
338  return transformerMap;
339 }
340 
341 bool QgsSizeScaleTransformer::loadVariant( const QVariant &transformer )
342 {
344 
345  QVariantMap transformerMap = transformer.toMap();
346 
347  mType = static_cast< ScaleType >( transformerMap.value( QStringLiteral( "scaleType" ), Linear ).toInt() );
348  mMinSize = transformerMap.value( QStringLiteral( "minSize" ), 0.0 ).toDouble();
349  mMaxSize = transformerMap.value( QStringLiteral( "maxSize" ), 1.0 ).toDouble();
350  mNullSize = transformerMap.value( QStringLiteral( "nullSize" ), 0.0 ).toDouble();
351  mExponent = transformerMap.value( QStringLiteral( "exponent" ), 1.0 ).toDouble();
352 
353  return true;
354 }
355 
356 double QgsSizeScaleTransformer::size( double value ) const
357 {
358  value = transformNumeric( value );
359 
360  switch ( mType )
361  {
362  case Linear:
363  return mMinSize + ( qBound( mMinValue, value, mMaxValue ) - mMinValue ) * ( mMaxSize - mMinSize ) / ( mMaxValue - mMinValue );
364 
365  case Area:
366  case Flannery:
367  case Exponential:
368  return mMinSize + std::pow( qBound( mMinValue, value, mMaxValue ) - mMinValue, mExponent ) * ( mMaxSize - mMinSize ) / std::pow( mMaxValue - mMinValue, mExponent );
369 
370  }
371  return 0;
372 }
373 
375 {
376  mType = type;
377  switch ( mType )
378  {
379  case Linear:
380  mExponent = 1.0;
381  break;
382  case Area:
383  mExponent = 0.5;
384  break;
385  case Flannery:
386  mExponent = 0.57;
387  break;
388  case Exponential:
389  //no change
390  break;
391  }
392 }
393 
394 QVariant QgsSizeScaleTransformer::transform( const QgsExpressionContext &context, const QVariant &value ) const
395 {
396  Q_UNUSED( context )
397 
398  if ( value.isNull() )
399  return mNullSize;
400 
401  bool ok;
402  double dblValue = value.toDouble( &ok );
403 
404  if ( ok )
405  {
406  //apply scaling to value
407  return size( dblValue );
408  }
409  else
410  {
411  return value;
412  }
413 }
414 
415 QString QgsSizeScaleTransformer::toExpression( const QString &baseExpression ) const
416 {
417  QString minValueString = QString::number( mMinValue );
418  QString maxValueString = QString::number( mMaxValue );
419  QString minSizeString = QString::number( mMinSize );
420  QString maxSizeString = QString::number( mMaxSize );
421  QString nullSizeString = QString::number( mNullSize );
422  QString exponentString = QString::number( mExponent );
423 
424  switch ( mType )
425  {
426  case Linear:
427  return QStringLiteral( "coalesce(scale_linear(%1, %2, %3, %4, %5), %6)" ).arg( baseExpression, minValueString, maxValueString, minSizeString, maxSizeString, nullSizeString );
428 
429  case Area:
430  case Flannery:
431  case Exponential:
432  return QStringLiteral( "coalesce(scale_exp(%1, %2, %3, %4, %5, %6), %7)" ).arg( baseExpression, minValueString, maxValueString, minSizeString, maxSizeString, exponentString, nullSizeString );
433 
434  }
435  return QString();
436 }
437 
438 QgsSizeScaleTransformer *QgsSizeScaleTransformer::fromExpression( const QString &expression, QString &baseExpression, QString &fieldName )
439 {
440  bool ok = false;
441 
443  double nullSize = 0.0;
444  double exponent = 1.0;
445 
446  baseExpression.clear();
447  fieldName.clear();
448 
449  QgsExpression e( expression );
450 
451  if ( !e.rootNode() )
452  return nullptr;
453 
454  const QgsExpressionNodeFunction *f = dynamic_cast<const QgsExpressionNodeFunction *>( e.rootNode() );
455  if ( !f )
456  return nullptr;
457 
458  QList<QgsExpressionNode *> args = f->args()->list();
459 
460  // the scale function may be enclosed in a coalesce(expr, 0) to avoid NULL value
461  // to be drawn with the default size
462  if ( "coalesce" == QgsExpression::Functions()[f->fnIndex()]->name() )
463  {
464  f = dynamic_cast<const QgsExpressionNodeFunction *>( args[0] );
465  if ( !f )
466  return nullptr;
467  nullSize = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
468  if ( ! ok )
469  return nullptr;
470  args = f->args()->list();
471  }
472 
473  if ( "scale_linear" == QgsExpression::Functions()[f->fnIndex()]->name() )
474  {
475  type = Linear;
476  }
477  else if ( "scale_exp" == QgsExpression::Functions()[f->fnIndex()]->name() )
478  {
479  exponent = QgsExpression( args[5]->dump() ).evaluate().toDouble( &ok );
480  if ( ! ok )
481  return nullptr;
482  if ( qgsDoubleNear( exponent, 0.57, 0.001 ) )
483  type = Flannery;
484  else if ( qgsDoubleNear( exponent, 0.5, 0.001 ) )
485  type = Area;
486  else
487  type = Exponential;
488  }
489  else
490  {
491  return nullptr;
492  }
493 
494  bool expOk = true;
495  double minValue = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
496  expOk &= ok;
497  double maxValue = QgsExpression( args[2]->dump() ).evaluate().toDouble( &ok );
498  expOk &= ok;
499  double minSize = QgsExpression( args[3]->dump() ).evaluate().toDouble( &ok );
500  expOk &= ok;
501  double maxSize = QgsExpression( args[4]->dump() ).evaluate().toDouble( &ok );
502  expOk &= ok;
503 
504  if ( !expOk )
505  {
506  return nullptr;
507  }
508 
509  if ( args[0]->nodeType() == QgsExpressionNode::ntColumnRef )
510  {
511  fieldName = static_cast< QgsExpressionNodeColumnRef * >( args[0] )->name();
512  }
513  else
514  {
515  baseExpression = args[0]->dump();
516  }
518 }
519 
520 
521 //
522 // QgsColorRampTransformer
523 //
524 
525 QgsColorRampTransformer::QgsColorRampTransformer( double minValue, double maxValue,
526  QgsColorRamp *ramp,
527  const QColor &nullColor )
528  : QgsPropertyTransformer( minValue, maxValue )
529  , mGradientRamp( ramp )
530  , mNullColor( nullColor )
531 {
532 
533 }
534 
536  : QgsPropertyTransformer( other )
537  , mGradientRamp( other.mGradientRamp ? other.mGradientRamp->clone() : nullptr )
538  , mNullColor( other.mNullColor )
539  , mRampName( other.mRampName )
540 {
541 
542 }
543 
545 {
547  mMinValue = other.mMinValue;
548  mMaxValue = other.mMaxValue;
549  mGradientRamp.reset( other.mGradientRamp ? other.mGradientRamp->clone() : nullptr );
550  mNullColor = other.mNullColor;
551  mRampName = other.mRampName;
552  return *this;
553 }
554 
556 {
557  std::unique_ptr< QgsColorRampTransformer > c( new QgsColorRampTransformer( mMinValue, mMaxValue,
558  mGradientRamp ? mGradientRamp->clone() : nullptr,
559  mNullColor ) );
560  c->setRampName( mRampName );
561  if ( mCurveTransform )
562  c->setCurveTransform( new QgsCurveTransform( *mCurveTransform ) );
563  return c.release();
564 }
565 
567 {
568  QVariantMap transformerMap = QgsPropertyTransformer::toVariant().toMap();
569 
570  if ( mGradientRamp )
571  {
572  transformerMap.insert( QStringLiteral( "colorramp" ), QgsSymbolLayerUtils::colorRampToVariant( QStringLiteral( "[source]" ), mGradientRamp.get() ) );
573  }
574  transformerMap.insert( QStringLiteral( "nullColor" ), QgsSymbolLayerUtils::encodeColor( mNullColor ) );
575  transformerMap.insert( QStringLiteral( "rampName" ), mRampName );
576 
577  return transformerMap;
578 }
579 
580 bool QgsColorRampTransformer::loadVariant( const QVariant &definition )
581 {
582  QVariantMap transformerMap = definition.toMap();
583 
585 
586  mGradientRamp.reset( nullptr );
587  if ( transformerMap.contains( QStringLiteral( "colorramp" ) ) )
588  {
589  setColorRamp( QgsSymbolLayerUtils::loadColorRamp( transformerMap.value( QStringLiteral( "colorramp" ) ).toMap() ) );
590  }
591 
592  mNullColor = QgsSymbolLayerUtils::decodeColor( transformerMap.value( QStringLiteral( "nullColor" ), QStringLiteral( "0,0,0,0" ) ).toString() );
593  mRampName = transformerMap.value( QStringLiteral( "rampName" ) ).toString();
594  return true;
595 }
596 
597 QVariant QgsColorRampTransformer::transform( const QgsExpressionContext &context, const QVariant &value ) const
598 {
599  Q_UNUSED( context )
600 
601  if ( value.isNull() )
602  return mNullColor;
603 
604  bool ok;
605  double dblValue = value.toDouble( &ok );
606 
607  if ( ok )
608  {
609  //apply scaling to value
610  return color( dblValue );
611  }
612  else
613  {
614  return value;
615  }
616 }
617 
618 QString QgsColorRampTransformer::toExpression( const QString &baseExpression ) const
619 {
620  if ( !mGradientRamp )
621  return QgsExpression::quotedValue( mNullColor.name() );
622 
623  QString minValueString = QString::number( mMinValue );
624  QString maxValueString = QString::number( mMaxValue );
625  QString nullColorString = mNullColor.name();
626 
627  return QStringLiteral( "coalesce(ramp_color('%1',scale_linear(%2, %3, %4, 0, 1)), '%5')" ).arg( !mRampName.isEmpty() ? mRampName : QStringLiteral( "custom ramp" ),
628  baseExpression, minValueString, maxValueString, nullColorString );
629 }
630 
631 QColor QgsColorRampTransformer::color( double value ) const
632 {
633  value = transformNumeric( value );
634  double scaledVal = qBound( 0.0, ( value - mMinValue ) / ( mMaxValue - mMinValue ), 1.0 );
635 
636  if ( !mGradientRamp )
637  return mNullColor;
638 
639  return mGradientRamp->color( scaledVal );
640 }
641 
643 {
644  return mGradientRamp.get();
645 }
646 
648 {
649  mGradientRamp.reset( ramp );
650 }
651 
652 
653 //
654 // QgsCurveTransform
655 //
656 
657 bool sortByX( const QgsPointXY &a, const QgsPointXY &b )
658 {
659  return a.x() < b.x();
660 }
661 
663 {
664  mControlPoints << QgsPointXY( 0, 0 ) << QgsPointXY( 1, 1 );
665  calcSecondDerivativeArray();
666 }
667 
668 QgsCurveTransform::QgsCurveTransform( const QList<QgsPointXY> &controlPoints )
669  : mControlPoints( controlPoints )
670 {
671  std::sort( mControlPoints.begin(), mControlPoints.end(), sortByX );
672  calcSecondDerivativeArray();
673 }
674 
676 {
677  delete [] mSecondDerivativeArray;
678 }
679 
681  : mControlPoints( other.mControlPoints )
682 {
683  if ( other.mSecondDerivativeArray )
684  {
685  mSecondDerivativeArray = new double[ mControlPoints.count()];
686  memcpy( mSecondDerivativeArray, other.mSecondDerivativeArray, sizeof( double ) * mControlPoints.count() );
687  }
688 }
689 
691 {
692  if ( this != &other )
693  {
694  mControlPoints = other.mControlPoints;
695  if ( other.mSecondDerivativeArray )
696  {
697  delete [] mSecondDerivativeArray;
698  mSecondDerivativeArray = new double[ mControlPoints.count()];
699  memcpy( mSecondDerivativeArray, other.mSecondDerivativeArray, sizeof( double ) * mControlPoints.count() );
700  }
701  }
702  return *this;
703 }
704 
705 void QgsCurveTransform::setControlPoints( const QList<QgsPointXY> &points )
706 {
707  mControlPoints = points;
708  std::sort( mControlPoints.begin(), mControlPoints.end(), sortByX );
709  for ( int i = 0; i < mControlPoints.count(); ++i )
710  {
711  mControlPoints[ i ] = QgsPointXY( qBound( 0.0, mControlPoints.at( i ).x(), 1.0 ),
712  qBound( 0.0, mControlPoints.at( i ).y(), 1.0 ) );
713  }
714  calcSecondDerivativeArray();
715 }
716 
717 void QgsCurveTransform::addControlPoint( double x, double y )
718 {
719  QgsPointXY point( x, y );
720  if ( mControlPoints.contains( point ) )
721  return;
722 
723  mControlPoints << point;
724  std::sort( mControlPoints.begin(), mControlPoints.end(), sortByX );
725  calcSecondDerivativeArray();
726 }
727 
728 void QgsCurveTransform::removeControlPoint( double x, double y )
729 {
730  for ( int i = 0; i < mControlPoints.count(); ++i )
731  {
732  if ( qgsDoubleNear( mControlPoints.at( i ).x(), x )
733  && qgsDoubleNear( mControlPoints.at( i ).y(), y ) )
734  {
735  mControlPoints.removeAt( i );
736  break;
737  }
738  }
739  calcSecondDerivativeArray();
740 }
741 
742 // this code is adapted from https://github.com/OpenFibers/Photoshop-Curves
743 // which in turn was adapted from
744 // http://www.developpez.net/forums/d331608-3/autres-langages/algorithmes/contribuez/image-interpolation-spline-cubique/#post3513925 //#spellok
745 
746 double QgsCurveTransform::y( double x ) const
747 {
748  int n = mControlPoints.count();
749  if ( n < 2 )
750  return qBound( 0.0, x, 1.0 ); // invalid
751  else if ( n < 3 )
752  {
753  // linear
754  if ( x <= mControlPoints.at( 0 ).x() )
755  return qBound( 0.0, mControlPoints.at( 0 ).y(), 1.0 );
756  else if ( x >= mControlPoints.at( n - 1 ).x() )
757  return qBound( 0.0, mControlPoints.at( 1 ).y(), 1.0 );
758  else
759  {
760  double dx = mControlPoints.at( 1 ).x() - mControlPoints.at( 0 ).x();
761  double dy = mControlPoints.at( 1 ).y() - mControlPoints.at( 0 ).y();
762  return qBound( 0.0, ( x - mControlPoints.at( 0 ).x() ) * ( dy / dx ) + mControlPoints.at( 0 ).y(), 1.0 );
763  }
764  }
765 
766  // safety check
767  if ( x <= mControlPoints.at( 0 ).x() )
768  return qBound( 0.0, mControlPoints.at( 0 ).y(), 1.0 );
769  if ( x >= mControlPoints.at( n - 1 ).x() )
770  return qBound( 0.0, mControlPoints.at( n - 1 ).y(), 1.0 );
771 
772  // find corresponding segment
773  QList<QgsPointXY>::const_iterator pointIt = mControlPoints.constBegin();
774  QgsPointXY currentControlPoint = *pointIt;
775  ++pointIt;
776  QgsPointXY nextControlPoint = *pointIt;
777 
778  for ( int i = 0; i < n - 1; ++i )
779  {
780  if ( x < nextControlPoint.x() )
781  {
782  // found segment
783  double h = nextControlPoint.x() - currentControlPoint.x();
784  double t = ( x - currentControlPoint.x() ) / h;
785 
786  double a = 1 - t;
787 
788  return qBound( 0.0, a * currentControlPoint.y() + t * nextControlPoint.y() + ( h * h / 6 ) * ( ( a * a * a - a ) * mSecondDerivativeArray[i] + ( t * t * t - t ) * mSecondDerivativeArray[i + 1] ),
789  1.0 );
790  }
791 
792  ++pointIt;
793  if ( pointIt == mControlPoints.constEnd() )
794  break;
795 
796  currentControlPoint = nextControlPoint;
797  nextControlPoint = *pointIt;
798  }
799 
800  //should not happen
801  return qBound( 0.0, x, 1.0 );
802 }
803 
804 // this code is adapted from https://github.com/OpenFibers/Photoshop-Curves
805 // which in turn was adapted from
806 // http://www.developpez.net/forums/d331608-3/autres-langages/algorithmes/contribuez/image-interpolation-spline-cubique/#post3513925 //#spellok
807 
808 QVector<double> QgsCurveTransform::y( const QVector<double> &x ) const
809 {
810  QVector<double> result;
811 
812  int n = mControlPoints.count();
813  if ( n < 3 )
814  {
815  // invalid control points - use simple transform
816  const auto constX = x;
817  for ( double i : constX )
818  result << y( i );
819 
820  return result;
821  }
822 
823  // find corresponding segment
824  QList<QgsPointXY>::const_iterator pointIt = mControlPoints.constBegin();
825  QgsPointXY currentControlPoint = *pointIt;
826  ++pointIt;
827  QgsPointXY nextControlPoint = *pointIt;
828 
829  int xIndex = 0;
830  double currentX = x.at( xIndex );
831  // safety check
832  while ( currentX <= currentControlPoint.x() )
833  {
834  result << qBound( 0.0, currentControlPoint.y(), 1.0 );
835  xIndex++;
836  currentX = x.at( xIndex );
837  }
838 
839  for ( int i = 0; i < n - 1; ++i )
840  {
841  while ( currentX < nextControlPoint.x() )
842  {
843  // found segment
844  double h = nextControlPoint.x() - currentControlPoint.x();
845 
846  double t = ( currentX - currentControlPoint.x() ) / h;
847 
848  double a = 1 - t;
849 
850  result << qBound( 0.0, a * currentControlPoint.y() + t * nextControlPoint.y() + ( h * h / 6 ) * ( ( a * a * a - a )*mSecondDerivativeArray[i] + ( t * t * t - t )*mSecondDerivativeArray[i + 1] ), 1.0 );
851  xIndex++;
852  if ( xIndex == x.count() )
853  return result;
854 
855  currentX = x.at( xIndex );
856  }
857 
858  ++pointIt;
859  if ( pointIt == mControlPoints.constEnd() )
860  break;
861 
862  currentControlPoint = nextControlPoint;
863  nextControlPoint = *pointIt;
864  }
865 
866  // safety check
867  while ( xIndex < x.count() )
868  {
869  result << qBound( 0.0, nextControlPoint.y(), 1.0 );
870  xIndex++;
871  }
872 
873  return result;
874 }
875 
876 bool QgsCurveTransform::readXml( const QDomElement &elem, const QDomDocument & )
877 {
878  QString xString = elem.attribute( QStringLiteral( "x" ) );
879  QString yString = elem.attribute( QStringLiteral( "y" ) );
880 
881  QStringList xVals = xString.split( ',' );
882  QStringList yVals = yString.split( ',' );
883  if ( xVals.count() != yVals.count() )
884  return false;
885 
886  QList< QgsPointXY > newPoints;
887  bool ok = false;
888  for ( int i = 0; i < xVals.count(); ++i )
889  {
890  double x = xVals.at( i ).toDouble( &ok );
891  if ( !ok )
892  return false;
893  double y = yVals.at( i ).toDouble( &ok );
894  if ( !ok )
895  return false;
896  newPoints << QgsPointXY( x, y );
897  }
898  setControlPoints( newPoints );
899  return true;
900 }
901 
902 bool QgsCurveTransform::writeXml( QDomElement &transformElem, QDomDocument & ) const
903 {
904  QStringList x;
905  QStringList y;
906  const auto constMControlPoints = mControlPoints;
907  for ( const QgsPointXY &p : constMControlPoints )
908  {
909  x << qgsDoubleToString( p.x() );
910  y << qgsDoubleToString( p.y() );
911  }
912 
913  transformElem.setAttribute( QStringLiteral( "x" ), x.join( ',' ) );
914  transformElem.setAttribute( QStringLiteral( "y" ), y.join( ',' ) );
915 
916  return true;
917 }
918 
920 {
921  QVariantMap transformMap;
922 
923  QStringList x;
924  QStringList y;
925  const auto constMControlPoints = mControlPoints;
926  for ( const QgsPointXY &p : constMControlPoints )
927  {
928  x << qgsDoubleToString( p.x() );
929  y << qgsDoubleToString( p.y() );
930  }
931 
932  transformMap.insert( QStringLiteral( "x" ), x.join( ',' ) );
933  transformMap.insert( QStringLiteral( "y" ), y.join( ',' ) );
934 
935  return transformMap;
936 }
937 
938 bool QgsCurveTransform::loadVariant( const QVariant &transformer )
939 {
940  QVariantMap transformMap = transformer.toMap();
941 
942  QString xString = transformMap.value( QStringLiteral( "x" ) ).toString();
943  QString yString = transformMap.value( QStringLiteral( "y" ) ).toString();
944 
945  QStringList xVals = xString.split( ',' );
946  QStringList yVals = yString.split( ',' );
947  if ( xVals.count() != yVals.count() )
948  return false;
949 
950  QList< QgsPointXY > newPoints;
951  bool ok = false;
952  for ( int i = 0; i < xVals.count(); ++i )
953  {
954  double x = xVals.at( i ).toDouble( &ok );
955  if ( !ok )
956  return false;
957  double y = yVals.at( i ).toDouble( &ok );
958  if ( !ok )
959  return false;
960  newPoints << QgsPointXY( x, y );
961  }
962  setControlPoints( newPoints );
963  return true;
964 }
965 
966 // this code is adapted from https://github.com/OpenFibers/Photoshop-Curves
967 // which in turn was adapted from
968 // http://www.developpez.net/forums/d331608-3/autres-langages/algorithmes/contribuez/image-interpolation-spline-cubique/#post3513925 //#spellok
969 
970 void QgsCurveTransform::calcSecondDerivativeArray()
971 {
972  int n = mControlPoints.count();
973  if ( n < 3 )
974  return; // cannot proceed
975 
976  delete[] mSecondDerivativeArray;
977 
978  double *matrix = new double[ n * 3 ];
979  double *result = new double[ n ];
980  matrix[0] = 0;
981  matrix[1] = 1;
982  matrix[2] = 0;
983  result[0] = 0;
984  QList<QgsPointXY>::const_iterator pointIt = mControlPoints.constBegin();
985  QgsPointXY pointIm1 = *pointIt;
986  ++pointIt;
987  QgsPointXY pointI = *pointIt;
988  ++pointIt;
989  QgsPointXY pointIp1 = *pointIt;
990 
991  for ( int i = 1; i < n - 1; ++i )
992  {
993  matrix[i * 3 + 0 ] = ( pointI.x() - pointIm1.x() ) / 6.0;
994  matrix[i * 3 + 1 ] = ( pointIp1.x() - pointIm1.x() ) / 3.0;
995  matrix[i * 3 + 2 ] = ( pointIp1.x() - pointI.x() ) / 6.0;
996  result[i] = ( pointIp1.y() - pointI.y() ) / ( pointIp1.x() - pointI.x() ) - ( pointI.y() - pointIm1.y() ) / ( pointI.x() - pointIm1.x() );
997 
998  // shuffle points
999  pointIm1 = pointI;
1000  pointI = pointIp1;
1001  ++pointIt;
1002  if ( pointIt == mControlPoints.constEnd() )
1003  break;
1004 
1005  pointIp1 = *pointIt;
1006  }
1007  matrix[( n - 1 ) * 3 + 0] = 0;
1008  matrix[( n - 1 ) * 3 + 1] = 1;
1009  matrix[( n - 1 ) * 3 + 2] = 0;
1010  result[n - 1] = 0;
1011 
1012  // solving pass1 (up->down)
1013  for ( int i = 1; i < n; ++i )
1014  {
1015  double k = matrix[i * 3 + 0] / matrix[( i - 1 ) * 3 + 1];
1016  matrix[i * 3 + 1] -= k * matrix[( i - 1 ) * 3 + 2];
1017  matrix[i * 3 + 0] = 0;
1018  result[i] -= k * result[i - 1];
1019  }
1020  // solving pass2 (down->up)
1021  for ( int i = n - 2; i >= 0; --i )
1022  {
1023  double k = matrix[i * 3 + 2] / matrix[( i + 1 ) * 3 + 1];
1024  matrix[i * 3 + 1] -= k * matrix[( i + 1 ) * 3 + 0];
1025  matrix[i * 3 + 2] = 0;
1026  result[i] -= k * result[i + 1];
1027  }
1028 
1029  // return second derivative value for each point
1030  mSecondDerivativeArray = new double[n];
1031  for ( int i = 0; i < n; ++i )
1032  {
1033  mSecondDerivativeArray[i] = result[i] / matrix[( i * 3 ) + 1];
1034  }
1035 
1036  delete[] result;
1037  delete[] matrix;
1038 }
1039 
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:370
QgsColorRamp
Abstract base class for color ramps.
Definition: qgscolorramp.h:32
QgsSymbolLayerUtils::encodeColor
static QString encodeColor(const QColor &color)
Definition: qgssymbollayerutils.cpp:52
QgsPointXY::y
double y
Definition: qgspointxy.h:48
QgsGenericNumericTransformer::transform
QVariant transform(const QgsExpressionContext &context, const QVariant &value) const override
Calculates the transform of a value.
Definition: qgspropertytransformer.cpp:190
QgsSizeScaleTransformer::clone
QgsSizeScaleTransformer * clone() const override
Returns a clone of the transformer.
Definition: qgspropertytransformer.cpp:314
QgsSizeScaleTransformer::Exponential
@ Exponential
Scale using set exponent.
Definition: qgspropertytransformer.h:471
qgspropertytransformer.h
QgsPropertyTransformer
Abstract base class for objects which transform the calculated value of a property.
Definition: qgspropertytransformer.h:171
qgsexpression.h
QgsExpressionNode::ntColumnRef
@ ntColumnRef
Definition: qgsexpressionnode.h:81
QgsPointXY::x
Q_GADGET double x
Definition: qgspointxy.h:47
QgsSizeScaleTransformer::type
ScaleType type() const
Returns the size transformer's scaling type (the method used to calculate the size from a value).
Definition: qgspropertytransformer.h:581
QgsPropertyTransformer::QgsPropertyTransformer
QgsPropertyTransformer(double minValue=0.0, double maxValue=1.0)
Constructor for QgsPropertyTransformer.
Definition: qgspropertytransformer.cpp:48
QgsExpression::rootNode
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Definition: qgsexpression.cpp:1091
QgsExpressionNodeColumnRef
An expression node which takes it value from a feature's field.
Definition: qgsexpressionnodeimpl.h:401
QgsExpressionNodeFunction::fnIndex
int fnIndex() const
Returns the index of the node's function.
Definition: qgsexpressionnodeimpl.h:331
qgssymbollayerutils.h
QgsColorRampTransformer::operator=
QgsColorRampTransformer & operator=(const QgsColorRampTransformer &other)
Definition: qgspropertytransformer.cpp:544
QgsSizeScaleTransformer::toVariant
QVariant toVariant() const override
Saves this transformer to a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:328
QgsGenericNumericTransformer::QgsGenericNumericTransformer
QgsGenericNumericTransformer(double minValue=0.0, double maxValue=1.0, double minOutput=0.0, double maxOutput=1.0, double nullOutput=0.0, double exponent=1.0)
Constructor for QgsGenericNumericTransformer.
Definition: qgspropertytransformer.cpp:132
QgsColorRampTransformer
QgsPropertyTransformer subclass for transforming a numeric value into a color from a color ramp.
Definition: qgspropertytransformer.h:609
QgsCurveTransform::setControlPoints
void setControlPoints(const QList< QgsPointXY > &points)
Sets the list of control points for the transform.
Definition: qgspropertytransformer.cpp:705
QgsPropertyTransformer::transformNumeric
double transformNumeric(double input) const
Applies base class numeric transformations.
Definition: qgspropertytransformer.cpp:113
QgsSizeScaleTransformer::QgsSizeScaleTransformer
QgsSizeScaleTransformer(ScaleType type=Linear, double minValue=0.0, double maxValue=1.0, double minSize=0.0, double maxSize=1.0, double nullSize=0.0, double exponent=1.0)
Constructor for QgsSizeScaleTransformer.
Definition: qgspropertytransformer.cpp:304
QgsCurveTransform::writeXml
bool writeXml(QDomElement &transformElem, QDomDocument &doc) const
Writes the current state of the transform into an XML element.
Definition: qgspropertytransformer.cpp:902
QgsSymbolLayerUtils::decodeColor
static QColor decodeColor(const QString &str)
Definition: qgssymbollayerutils.cpp:57
QgsPropertyTransformer::SizeScaleTransformer
@ SizeScaleTransformer
Size scaling transformer (QgsSizeScaleTransformer)
Definition: qgspropertytransformer.h:192
QgsGenericNumericTransformer::toExpression
QString toExpression(const QString &baseExpression) const override
Converts the transformer to a QGIS expression string.
Definition: qgspropertytransformer.cpp:211
qgsDoubleToString
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:275
QgsColorRampTransformer::loadVariant
bool loadVariant(const QVariant &definition) override
Loads this transformer from a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:580
QgsGenericNumericTransformer::loadVariant
bool loadVariant(const QVariant &definition) override
Loads this transformer from a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:165
QgsPropertyTransformer::ColorRampTransformer
@ ColorRampTransformer
Color ramp transformer (QgsColorRampTransformer)
Definition: qgspropertytransformer.h:193
QgsColorRampTransformer::QgsColorRampTransformer
QgsColorRampTransformer(double minValue=0.0, double maxValue=1.0, QgsColorRamp *ramp=nullptr, const QColor &nullColor=QColor(0, 0, 0, 0))
Constructor for QgsColorRampTransformer.
Definition: qgspropertytransformer.cpp:525
QgsExpression::quotedValue
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
Definition: qgsexpression.cpp:79
QgsExpressionNodeFunction::args
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
Definition: qgsexpressionnodeimpl.h:336
QgsColorRampTransformer::colorRamp
QgsColorRamp * colorRamp() const
Returns the color ramp used for calculating property colors.
Definition: qgspropertytransformer.cpp:642
qgscolorramp.h
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsSizeScaleTransformer::loadVariant
bool loadVariant(const QVariant &definition) override
Loads this transformer from a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:341
QgsColorRampTransformer::toVariant
QVariant toVariant() const override
Saves this transformer to a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:566
QgsCurveTransform::~QgsCurveTransform
~QgsCurveTransform()
Definition: qgspropertytransformer.cpp:675
QgsSizeScaleTransformer
QgsPropertyTransformer subclass for scaling a value into a size according to various scaling methods.
Definition: qgspropertytransformer.h:462
QgsPropertyTransformer::mMaxValue
double mMaxValue
Maximum value expected by the transformer.
Definition: qgspropertytransformer.h:329
QgsSizeScaleTransformer::Flannery
@ Flannery
Flannery scaling method.
Definition: qgspropertytransformer.h:470
QgsGenericNumericTransformer::toVariant
QVariant toVariant() const override
Saves this transformer to a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:153
QgsExpressionNodeColumnRef::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:1364
QgsSizeScaleTransformer::fromExpression
static QgsSizeScaleTransformer * fromExpression(const QString &expression, QString &baseExpression, QString &fieldName)
Attempts to parse an expression into a corresponding QgsSizeScaleTransformer.
Definition: qgspropertytransformer.cpp:438
QgsGenericNumericTransformer::clone
QgsGenericNumericTransformer * clone() const override
Returns a clone of the transformer.
Definition: qgspropertytransformer.cpp:140
QgsSizeScaleTransformer::maxSize
double maxSize() const
Returns the maximum calculated size.
Definition: qgspropertytransformer.h:539
QgsExpressionNodeFunction
An expression node for expression functions.
Definition: qgsexpressionnodeimpl.h:317
QgsCurveTransform::loadVariant
bool loadVariant(const QVariant &transformer)
Load this curve transformer from a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:938
QgsColorRampTransformer::toExpression
QString toExpression(const QString &baseExpression) const override
Converts the transformer to a QGIS expression string.
Definition: qgspropertytransformer.cpp:618
QgsExpression::Functions
static const QList< QgsExpressionFunction * > & Functions()
Definition: qgsexpressionfunction.cpp:6008
QgsExpression::evaluate
QVariant evaluate()
Evaluate the feature and return the result.
Definition: qgsexpression.cpp:346
sortByX
bool sortByX(const QgsPointXY &a, const QgsPointXY &b)
Definition: qgspropertytransformer.cpp:657
QgsCurveTransform::QgsCurveTransform
QgsCurveTransform()
Constructs a default QgsCurveTransform which linearly maps values between 0 and 1 unchanged.
Definition: qgspropertytransformer.cpp:662
QgsSizeScaleTransformer::toExpression
QString toExpression(const QString &baseExpression) const override
Converts the transformer to a QGIS expression string.
Definition: qgspropertytransformer.cpp:415
QgsPropertyTransformer::maxValue
double maxValue() const
Returns the maximum value expected by the transformer.
Definition: qgspropertytransformer.h:263
QgsSymbolLayerUtils::loadColorRamp
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
Definition: qgssymbollayerutils.cpp:3087
QgsCurveTransform
Handles scaling of input values to output values by using a curve created from smoothly joining a num...
Definition: qgspropertytransformer.h:57
QgsExpressionNode::NodeList::list
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Definition: qgsexpressionnode.h:144
QgsSizeScaleTransformer::size
double size(double value) const
Calculates the size corresponding to a specific value.
Definition: qgspropertytransformer.cpp:356
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsPropertyTransformer::~QgsPropertyTransformer
virtual ~QgsPropertyTransformer()
QgsPropertyTransformer::minValue
double minValue() const
Returns the minimum value expected by the transformer.
Definition: qgspropertytransformer.h:248
QgsColorRampTransformer::transform
QVariant transform(const QgsExpressionContext &context, const QVariant &value) const override
Calculates the transform of a value.
Definition: qgspropertytransformer.cpp:597
QgsCurveTransform::y
double y(double x) const
Returns the mapped y value corresponding to the specified x value.
Definition: qgspropertytransformer.cpp:746
QgsSizeScaleTransformer::exponent
double exponent() const
Returns the exponent for an exponential expression.
Definition: qgspropertytransformer.h:567
QgsSizeScaleTransformer::Area
@ Area
Area based scaling.
Definition: qgspropertytransformer.h:469
QgsSizeScaleTransformer::Linear
@ Linear
Linear scaling.
Definition: qgspropertytransformer.h:468
qgsexpressionnodeimpl.h
QgsCurveTransform::toVariant
QVariant toVariant() const
Saves this curve transformer to a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:919
QgsPropertyTransformer::GenericNumericTransformer
@ GenericNumericTransformer
Generic transformer for numeric values (QgsGenericNumericTransformer)
Definition: qgspropertytransformer.h:191
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsPropertyTransformer::operator=
QgsPropertyTransformer & operator=(const QgsPropertyTransformer &other)
Definition: qgspropertytransformer.cpp:59
QgsGenericNumericTransformer::value
double value(double input) const
Calculates the size corresponding to a specific input value.
Definition: qgspropertytransformer.cpp:178
QgsCurveTransform::addControlPoint
void addControlPoint(double x, double y)
Adds a control point to the transform.
Definition: qgspropertytransformer.cpp:717
QgsSymbolLayerUtils::colorRampToVariant
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
Definition: qgssymbollayerutils.cpp:3122
QgsSizeScaleTransformer::nullSize
double nullSize() const
Returns the size value when an expression evaluates to NULL.
Definition: qgspropertytransformer.h:553
QgsPropertyTransformer::fromExpression
static QgsPropertyTransformer * fromExpression(const QString &expression, QString &baseExpression, QString &fieldName)
Attempts to parse an expression into a corresponding property transformer.
Definition: qgspropertytransformer.cpp:102
QgsPropertyTransformer::Type
Type
Transformer types.
Definition: qgspropertytransformer.h:190
QgsPropertyTransformer::loadVariant
virtual bool loadVariant(const QVariant &transformer)
Loads this transformer from a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:69
QgsPropertyTransformer::create
static QgsPropertyTransformer * create(Type type)
Factory method for creating a new property transformer of the specified type.
Definition: qgspropertytransformer.cpp:30
QgsColorRampTransformer::color
QColor color(double value) const
Calculates the color corresponding to a specific value.
Definition: qgspropertytransformer.cpp:631
QgsGenericNumericTransformer
QgsPropertyTransformer subclass for scaling an input numeric value into an output numeric value.
Definition: qgspropertytransformer.h:344
QgsPropertyTransformer::mMinValue
double mMinValue
Minimum value expected by the transformer.
Definition: qgspropertytransformer.h:326
QgsSizeScaleTransformer::transform
QVariant transform(const QgsExpressionContext &context, const QVariant &value) const override
Calculates the transform of a value.
Definition: qgspropertytransformer.cpp:394
QgsColorRampTransformer::setColorRamp
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp to use for calculating property colors.
Definition: qgspropertytransformer.cpp:647
QgsPropertyTransformer::mCurveTransform
std::unique_ptr< QgsCurveTransform > mCurveTransform
Optional curve transform.
Definition: qgspropertytransformer.h:332
QgsCurveTransform::operator=
QgsCurveTransform & operator=(const QgsCurveTransform &other)
Definition: qgspropertytransformer.cpp:690
QgsSizeScaleTransformer::ScaleType
ScaleType
Size scaling methods.
Definition: qgspropertytransformer.h:467
qgslogger.h
QgsGenericNumericTransformer::exponent
double exponent() const
Returns the exponent for an exponential expression.
Definition: qgspropertytransformer.h:436
QgsCurveTransform::removeControlPoint
void removeControlPoint(double x, double y)
Removes a control point from the transform.
Definition: qgspropertytransformer.cpp:728
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:105
QgsGenericNumericTransformer::fromExpression
static QgsGenericNumericTransformer * fromExpression(const QString &expression, QString &baseExpression, QString &fieldName)
Attempts to parse an expression into a corresponding QgsSizeScaleTransformer.
Definition: qgspropertytransformer.cpp:226
QgsColorRampTransformer::clone
QgsColorRampTransformer * clone() const override
Returns a clone of the transformer.
Definition: qgspropertytransformer.cpp:555
QgsCurveTransform::readXml
bool readXml(const QDomElement &elem, const QDomDocument &doc)
Reads the curve's state from an XML element.
Definition: qgspropertytransformer.cpp:876
qgspointxy.h
QgsPropertyTransformer::toVariant
virtual QVariant toVariant() const
Saves this transformer to a QVariantMap, wrapped in a QVariant.
Definition: qgspropertytransformer.cpp:88
QgsSizeScaleTransformer::minSize
double minSize() const
Returns the minimum calculated size.
Definition: qgspropertytransformer.h:525
QgsSizeScaleTransformer::setType
void setType(ScaleType type)
Sets the size transformer's scaling type (the method used to calculate the size from a value).
Definition: qgspropertytransformer.cpp:374