49 : mMinValue( minValue )
50 , mMaxValue( maxValue )
54 : mMinValue( other.mMinValue )
55 , mMaxValue( other.mMaxValue )
56 , mCurveTransform( other.mCurveTransform ? new
QgsCurveTransform( *other.mCurveTransform ) : nullptr )
71 QVariantMap transformerMap = transformer.toMap();
73 mMinValue = transformerMap.value( QStringLiteral(
"minValue" ), 0.0 ).toDouble();
74 mMaxValue = transformerMap.value( QStringLiteral(
"maxValue" ), 1.0 ).toDouble();
77 QVariantMap curve = transformerMap.value( QStringLiteral(
"curve" ) ).toMap();
79 if ( !curve.isEmpty() )
90 QVariantMap transformerMap;
92 transformerMap.insert( QStringLiteral(
"minValue" ),
mMinValue );
93 transformerMap.insert( QStringLiteral(
"maxValue" ),
mMaxValue );
97 transformerMap.insert( QStringLiteral(
"curve" ),
mCurveTransform->toVariant() );
99 return transformerMap;
104 baseExpression.clear();
134 , mMinOutput( minOutput )
135 , mMaxOutput( maxOutput )
136 , mNullOutput( nullOutput )
137 , mExponent( exponent )
157 transformerMap.insert( QStringLiteral(
"minOutput" ), mMinOutput );
158 transformerMap.insert( QStringLiteral(
"maxOutput" ), mMaxOutput );
159 transformerMap.insert( QStringLiteral(
"nullOutput" ), mNullOutput );
160 transformerMap.insert( QStringLiteral(
"exponent" ), mExponent );
162 return transformerMap;
169 QVariantMap transformerMap = transformer.toMap();
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();
181 return std::clamp( input, mMinOutput, mMaxOutput );
198 double dblValue = v.toDouble( &ok );
203 return value( dblValue );
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 );
221 return QStringLiteral(
"coalesce(scale_linear(%1, %2, %3, %4, %5), %6)" ).arg( baseExpression, minValueString, maxValueString, minOutputString, maxOutputString, nullOutputString );
223 return QStringLiteral(
"coalesce(scale_exp(%1, %2, %3, %4, %5, %6), %7)" ).arg( baseExpression, minValueString, maxValueString, minOutputString, maxOutputString, exponentString, nullOutputString );
230 double nullValue = 0.0;
233 baseExpression.clear();
245 QList<QgsExpressionNode *> args = f->
args()->
list();
294 baseExpression = args[0]->
dump();
306 , mMinSize( minSize )
307 , mMaxSize( maxSize )
308 , mNullSize( nullSize )
309 , mExponent( exponent )
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 );
338 return transformerMap;
345 QVariantMap transformerMap = transformer.toMap();
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();
398 if ( value.isNull() )
402 double dblValue = value.toDouble( &ok );
407 return size( dblValue );
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 );
427 return QStringLiteral(
"coalesce(scale_linear(%1, %2, %3, %4, %5), %6)" ).arg( baseExpression, minValueString, maxValueString, minSizeString, maxSizeString, nullSizeString );
432 return QStringLiteral(
"coalesce(scale_exp(%1, %2, %3, %4, %5, %6), %7)" ).arg( baseExpression, minValueString, maxValueString, minSizeString, maxSizeString, exponentString, nullSizeString );
446 baseExpression.clear();
458 QList<QgsExpressionNode *> args = f->
args()->
list();
515 baseExpression = args[0]->
dump();
527 const QColor &nullColor )
529 , mGradientRamp( ramp )
530 , mNullColor( nullColor )
537 , mGradientRamp( other.mGradientRamp ? other.mGradientRamp->clone() : nullptr )
538 , mNullColor( other.mNullColor )
539 , mRampName( other.mRampName )
549 mGradientRamp.reset( other.mGradientRamp ? other.mGradientRamp->clone() :
nullptr );
550 mNullColor = other.mNullColor;
551 mRampName = other.mRampName;
558 mGradientRamp ? mGradientRamp->clone() :
nullptr,
560 c->setRampName( mRampName );
575 transformerMap.insert( QStringLiteral(
"rampName" ), mRampName );
577 return transformerMap;
582 QVariantMap transformerMap = definition.toMap();
586 mGradientRamp.reset(
nullptr );
587 if ( transformerMap.contains( QStringLiteral(
"colorramp" ) ) )
593 mRampName = transformerMap.value( QStringLiteral(
"rampName" ) ).toString();
601 if ( value.isNull() )
605 double dblValue = value.toDouble( &ok );
610 return color( dblValue );
620 if ( !mGradientRamp )
623 QString minValueString = QString::number(
mMinValue );
624 QString maxValueString = QString::number(
mMaxValue );
625 QString nullColorString = mNullColor.name();
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 );
636 if ( !mGradientRamp )
639 return mGradientRamp->color( scaledVal );
644 return mGradientRamp.get();
649 mGradientRamp.reset( ramp );
659 return a.
x() < b.
x();
665 calcSecondDerivativeArray();
669 : mControlPoints( controlPoints )
671 std::sort( mControlPoints.begin(), mControlPoints.end(),
sortByX );
672 calcSecondDerivativeArray();
677 delete [] mSecondDerivativeArray;
681 : mControlPoints( other.mControlPoints )
683 if ( other.mSecondDerivativeArray )
685 mSecondDerivativeArray =
new double[ mControlPoints.count()];
686 memcpy( mSecondDerivativeArray, other.mSecondDerivativeArray,
sizeof(
double ) * mControlPoints.count() );
692 if (
this != &other )
694 mControlPoints = other.mControlPoints;
695 if ( other.mSecondDerivativeArray )
697 delete [] mSecondDerivativeArray;
698 mSecondDerivativeArray =
new double[ mControlPoints.count()];
699 memcpy( mSecondDerivativeArray, other.mSecondDerivativeArray,
sizeof(
double ) * mControlPoints.count() );
707 mControlPoints = points;
708 std::sort( mControlPoints.begin(), mControlPoints.end(),
sortByX );
709 for (
int i = 0; i < mControlPoints.count(); ++i )
711 mControlPoints[ i ] =
QgsPointXY( std::clamp( mControlPoints.at( i ).x(), 0.0, 1.0 ),
712 std::clamp( mControlPoints.at( i ).y(), 0.0, 1.0 ) );
714 calcSecondDerivativeArray();
720 if ( mControlPoints.contains( point ) )
723 mControlPoints << point;
724 std::sort( mControlPoints.begin(), mControlPoints.end(),
sortByX );
725 calcSecondDerivativeArray();
730 for (
int i = 0; i < mControlPoints.count(); ++i )
735 mControlPoints.removeAt( i );
739 calcSecondDerivativeArray();
748 int n = mControlPoints.count();
750 return std::clamp( x, 0.0, 1.0 );
754 if ( x <= mControlPoints.at( 0 ).x() )
755 return std::clamp( mControlPoints.at( 0 ).y(), 0.0, 1.0 );
756 else if ( x >= mControlPoints.at( n - 1 ).x() )
757 return std::clamp( mControlPoints.at( 1 ).y(), 0.0, 1.0 );
760 double dx = mControlPoints.at( 1 ).x() - mControlPoints.at( 0 ).x();
761 double dy = mControlPoints.at( 1 ).y() - mControlPoints.at( 0 ).y();
762 return std::clamp( ( x - mControlPoints.at( 0 ).x() ) * ( dy / dx ) + mControlPoints.at( 0 ).y(), 0.0, 1.0 );
767 if ( x <= mControlPoints.at( 0 ).x() )
768 return std::clamp( mControlPoints.at( 0 ).y(), 0.0, 1.0 );
769 if ( x >= mControlPoints.at( n - 1 ).x() )
770 return std::clamp( mControlPoints.at( n - 1 ).y(), 0.0, 1.0 );
773 QList<QgsPointXY>::const_iterator pointIt = mControlPoints.constBegin();
778 for (
int i = 0; i < n - 1; ++i )
780 if ( x < nextControlPoint.
x() )
783 double h = nextControlPoint.
x() - currentControlPoint.
x();
784 double t = ( x - currentControlPoint.
x() ) / h;
788 return std::clamp( a * currentControlPoint.
y() + t * nextControlPoint.
y() + ( h * h / 6 ) * ( ( a * a * a - a ) * mSecondDerivativeArray[i] + ( t * t * t - t ) * mSecondDerivativeArray[i + 1] ),
793 if ( pointIt == mControlPoints.constEnd() )
796 currentControlPoint = nextControlPoint;
797 nextControlPoint = *pointIt;
801 return std::clamp( x, 0.0, 1.0 );
810 QVector<double> result;
812 int n = mControlPoints.count();
816 const auto constX = x;
817 for (
double i : constX )
824 QList<QgsPointXY>::const_iterator pointIt = mControlPoints.constBegin();
830 double currentX = x.at( xIndex );
832 while ( currentX <= currentControlPoint.
x() )
834 result << std::clamp( currentControlPoint.
y(), 0.0, 1.0 );
836 currentX = x.at( xIndex );
839 for (
int i = 0; i < n - 1; ++i )
841 while ( currentX < nextControlPoint.
x() )
844 double h = nextControlPoint.
x() - currentControlPoint.
x();
846 double t = ( currentX - currentControlPoint.
x() ) / h;
850 result << std::clamp( a * currentControlPoint.
y() + t * nextControlPoint.
y() + ( h * h / 6 ) * ( ( a * a * a - a )*mSecondDerivativeArray[i] + ( t * t * t - t )*mSecondDerivativeArray[i + 1] ), 0.0, 1.0 );
852 if ( xIndex == x.count() )
855 currentX = x.at( xIndex );
859 if ( pointIt == mControlPoints.constEnd() )
862 currentControlPoint = nextControlPoint;
863 nextControlPoint = *pointIt;
867 while ( xIndex < x.count() )
869 result << std::clamp( nextControlPoint.
y(), 0.0, 1.0 );
878 QString xString = elem.attribute( QStringLiteral(
"x" ) );
879 QString yString = elem.attribute( QStringLiteral(
"y" ) );
881 QStringList xVals = xString.split(
',' );
882 QStringList yVals = yString.split(
',' );
883 if ( xVals.count() != yVals.count() )
886 QList< QgsPointXY > newPoints;
888 for (
int i = 0; i < xVals.count(); ++i )
890 double x = xVals.at( i ).toDouble( &ok );
893 double y = yVals.at( i ).toDouble( &ok );
906 const auto constMControlPoints = mControlPoints;
907 for (
const QgsPointXY &p : constMControlPoints )
913 transformElem.setAttribute( QStringLiteral(
"x" ), x.join(
',' ) );
914 transformElem.setAttribute( QStringLiteral(
"y" ),
y.join(
',' ) );
921 QVariantMap transformMap;
925 const auto constMControlPoints = mControlPoints;
926 for (
const QgsPointXY &p : constMControlPoints )
932 transformMap.insert( QStringLiteral(
"x" ), x.join(
',' ) );
933 transformMap.insert( QStringLiteral(
"y" ),
y.join(
',' ) );
940 QVariantMap transformMap = transformer.toMap();
942 QString xString = transformMap.value( QStringLiteral(
"x" ) ).toString();
943 QString yString = transformMap.value( QStringLiteral(
"y" ) ).toString();
945 QStringList xVals = xString.split(
',' );
946 QStringList yVals = yString.split(
',' );
947 if ( xVals.count() != yVals.count() )
950 QList< QgsPointXY > newPoints;
952 for (
int i = 0; i < xVals.count(); ++i )
954 double x = xVals.at( i ).toDouble( &ok );
957 double y = yVals.at( i ).toDouble( &ok );
970 void QgsCurveTransform::calcSecondDerivativeArray()
972 int n = mControlPoints.count();
976 delete[] mSecondDerivativeArray;
978 double *matrix =
new double[ n * 3 ];
979 double *result =
new double[ n ];
984 QList<QgsPointXY>::const_iterator pointIt = mControlPoints.constBegin();
991 for (
int i = 1; i < n - 1; ++i )
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() );
1002 if ( pointIt == mControlPoints.constEnd() )
1005 pointIp1 = *pointIt;
1007 matrix[( n - 1 ) * 3 + 0] = 0;
1008 matrix[( n - 1 ) * 3 + 1] = 1;
1009 matrix[( n - 1 ) * 3 + 2] = 0;
1013 for (
int i = 1; i < n; ++i )
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];
1021 for (
int i = n - 2; i >= 0; --i )
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];
1030 mSecondDerivativeArray =
new double[n];
1031 for (
int i = 0; i < n; ++i )
1033 mSecondDerivativeArray[i] = result[i] / matrix[( i * 3 ) + 1];
Abstract base class for color ramps.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
An expression node which takes it value from a feature's field.
QString dump() const override
Dump this node into a serialized (part) of an expression.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Class for parsing and evaluation of expressions (formerly called "search strings").
static const QList< QgsExpressionFunction * > & Functions()
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
QVariant evaluate()
Evaluate the feature and return the result.
A class to represent a 2D point.
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
static QColor decodeColor(const QString &str)
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QString encodeColor(const QColor &color)
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
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)