30using namespace Qt::StringLiterals;
80 QVariantMap transformerMap = transformer.toMap();
82 mMinValue = transformerMap.value( u
"minValue"_s, 0.0 ).toDouble();
83 mMaxValue = transformerMap.value( u
"maxValue"_s, 1.0 ).toDouble();
86 QVariantMap curve = transformerMap.value( u
"curve"_s ).toMap();
88 if ( !curve.isEmpty() )
99 QVariantMap transformerMap;
101 transformerMap.insert( u
"minValue"_s,
mMinValue );
102 transformerMap.insert( u
"maxValue"_s,
mMaxValue );
108 return transformerMap;
113 baseExpression.clear();
143 , mMinOutput( minOutput )
144 , mMaxOutput( maxOutput )
145 , mNullOutput( nullOutput )
151 auto t = std::make_unique<QgsGenericNumericTransformer>(
mMinValue,
mMaxValue, mMinOutput, mMaxOutput, mNullOutput, mExponent );
161 transformerMap.insert( u
"minOutput"_s, mMinOutput );
162 transformerMap.insert( u
"maxOutput"_s, mMaxOutput );
163 transformerMap.insert( u
"nullOutput"_s, mNullOutput );
164 transformerMap.insert( u
"exponent"_s, mExponent );
166 return transformerMap;
173 QVariantMap transformerMap = transformer.toMap();
175 mMinOutput = transformerMap.value( u
"minOutput"_s, 0.0 ).toDouble();
176 mMaxOutput = transformerMap.value( u
"maxOutput"_s, 1.0 ).toDouble();
177 mNullOutput = transformerMap.value( u
"nullOutput"_s, 0.0 ).toDouble();
178 mExponent = transformerMap.value( u
"exponent"_s, 1.0 ).toDouble();
204 double dblValue = v.toDouble( &ok );
209 return value( dblValue );
219 QString minValueString = QString::number(
mMinValue );
220 QString maxValueString = QString::number(
mMaxValue );
221 QString minOutputString = QString::number( mMinOutput );
222 QString maxOutputString = QString::number( mMaxOutput );
223 QString nullOutputString = QString::number( mNullOutput );
224 QString exponentString = QString::number( mExponent );
227 return u
"coalesce(scale_linear(%1, %2, %3, %4, %5), %6)"_s.arg( baseExpression, minValueString, maxValueString, minOutputString, maxOutputString, nullOutputString );
229 return u
"coalesce(scale_polynomial(%1, %2, %3, %4, %5, %6), %7)"_s.arg( baseExpression, minValueString, maxValueString, minOutputString, maxOutputString, exponentString, nullOutputString );
236 double nullValue = 0.0;
239 baseExpression.clear();
251 QList<QgsExpressionNode *> args = f->
args()->
list();
258 if (
"coalesce" == fd->name() )
270 if (
"scale_linear" == fd->name() )
274 else if (
"scale_polynomial" == fd->name() )
304 baseExpression = args[0]->dump();
325 auto t = std::make_unique<QgsSizeScaleTransformer>( mType,
mMinValue,
mMaxValue, mMinSize, mMaxSize, mNullSize, mExponent );
335 transformerMap.insert( u
"scaleType"_s,
static_cast< int >( mType ) );
336 transformerMap.insert( u
"minSize"_s, mMinSize );
337 transformerMap.insert( u
"maxSize"_s, mMaxSize );
338 transformerMap.insert( u
"nullSize"_s, mNullSize );
339 transformerMap.insert( u
"exponent"_s, mExponent );
341 return transformerMap;
348 QVariantMap transformerMap = transformer.toMap();
350 mType =
static_cast< ScaleType >( transformerMap.value( u
"scaleType"_s,
Linear ).toInt() );
351 mMinSize = transformerMap.value( u
"minSize"_s, 0.0 ).toDouble();
352 mMaxSize = transformerMap.value( u
"maxSize"_s, 1.0 ).toDouble();
353 mNullSize = transformerMap.value( u
"nullSize"_s, 0.0 ).toDouble();
354 mExponent = transformerMap.value( u
"exponent"_s, 1.0 ).toDouble();
409 double dblValue = value.toDouble( &ok );
414 return size( dblValue );
424 QString minValueString = QString::number(
mMinValue );
425 QString maxValueString = QString::number(
mMaxValue );
426 QString minSizeString = QString::number( mMinSize );
427 QString maxSizeString = QString::number( mMaxSize );
428 QString nullSizeString = QString::number( mNullSize );
429 QString exponentString = QString::number( mExponent );
434 return u
"coalesce(scale_linear(%1, %2, %3, %4, %5), %6)"_s.arg( baseExpression, minValueString, maxValueString, minSizeString, maxSizeString, nullSizeString );
439 return u
"coalesce(scale_polynomial(%1, %2, %3, %4, %5, %6), %7)"_s.arg( baseExpression, minValueString, maxValueString, minSizeString, maxSizeString, exponentString, nullSizeString );
452 baseExpression.clear();
464 QList<QgsExpressionNode *> args = f->
args()->
list();
470 if (
"coalesce" == fd->name() )
482 if (
"scale_linear" == fd->name() )
486 else if (
"scale_polynomial" == fd->name() )
524 baseExpression = args[0]->dump();
536 , mGradientRamp( ramp )
543 , mGradientRamp( other.mGradientRamp ? other.mGradientRamp->
clone() : nullptr )
544 , mNullColor( other.mNullColor )
545 , mRampName( other.mRampName )
550 if ( &other ==
this )
556 mGradientRamp.reset( other.mGradientRamp ? other.mGradientRamp->clone() :
nullptr );
557 mNullColor = other.mNullColor;
558 mRampName = other.mRampName;
564 auto c = std::make_unique<QgsColorRampTransformer>(
mMinValue,
mMaxValue, mGradientRamp ? mGradientRamp->clone() :
nullptr, mNullColor );
565 c->setRampName( mRampName );
580 transformerMap.insert( u
"rampName"_s, mRampName );
582 return transformerMap;
587 QVariantMap transformerMap = definition.toMap();
591 mGradientRamp.reset(
nullptr );
592 if ( transformerMap.contains( u
"colorramp"_s ) )
598 mRampName = transformerMap.value( u
"rampName"_s ).toString();
610 double dblValue = value.toDouble( &ok );
615 return color( dblValue );
625 if ( !mGradientRamp )
628 QString minValueString = QString::number(
mMinValue );
629 QString maxValueString = QString::number(
mMaxValue );
630 QString nullColorString = mNullColor.name();
632 return u
"coalesce(ramp_color('%1',scale_linear(%2, %3, %4, 0, 1)), '%5')"_s.arg( !mRampName.isEmpty() ? mRampName : u
"custom ramp"_s, baseExpression, minValueString, maxValueString, nullColorString );
639 return mGradientRamp ? mGradientRamp->color( 0 ) : mNullColor;
645 if ( !mGradientRamp )
648 return mGradientRamp->color( scaledVal );
653 return mGradientRamp.get();
658 mGradientRamp.reset( ramp );
668 return a.
x() < b.
x();
674 calcSecondDerivativeArray();
680 std::sort( mControlPoints.begin(), mControlPoints.end(),
sortByX );
681 calcSecondDerivativeArray();
686 delete[] mSecondDerivativeArray;
690 : mControlPoints( other.mControlPoints )
692 if ( other.mSecondDerivativeArray )
694 mSecondDerivativeArray = new double[mControlPoints.count()];
695 memcpy( mSecondDerivativeArray, other.mSecondDerivativeArray, sizeof( double ) * mControlPoints.count() );
701 if (
this != &other )
703 mControlPoints = other.mControlPoints;
704 if ( other.mSecondDerivativeArray )
706 delete[] mSecondDerivativeArray;
707 mSecondDerivativeArray =
new double[mControlPoints.count()];
708 memcpy( mSecondDerivativeArray, other.mSecondDerivativeArray,
sizeof(
double ) * mControlPoints.count() );
716 mControlPoints = points;
717 std::sort( mControlPoints.begin(), mControlPoints.end(),
sortByX );
718 for (
int i = 0; i < mControlPoints.count(); ++i )
720 mControlPoints[i] =
QgsPointXY( std::clamp( mControlPoints.at( i ).x(), 0.0, 1.0 ), std::clamp( mControlPoints.at( i ).y(), 0.0, 1.0 ) );
722 calcSecondDerivativeArray();
728 if ( mControlPoints.contains( point ) )
731 mControlPoints << point;
732 std::sort( mControlPoints.begin(), mControlPoints.end(),
sortByX );
733 calcSecondDerivativeArray();
738 for (
int i = 0; i < mControlPoints.count(); ++i )
742 mControlPoints.removeAt( i );
746 calcSecondDerivativeArray();
755 int n = mControlPoints.count();
757 return std::clamp( x, 0.0, 1.0 );
761 if ( x <= mControlPoints.at( 0 ).x() )
762 return std::clamp( mControlPoints.at( 0 ).y(), 0.0, 1.0 );
763 else if ( x >= mControlPoints.at( n - 1 ).x() )
764 return std::clamp( mControlPoints.at( 1 ).y(), 0.0, 1.0 );
767 double dx = mControlPoints.at( 1 ).x() - mControlPoints.at( 0 ).x();
768 double dy = mControlPoints.at( 1 ).y() - mControlPoints.at( 0 ).y();
769 return std::clamp( ( x - mControlPoints.at( 0 ).x() ) * ( dy / dx ) + mControlPoints.at( 0 ).y(), 0.0, 1.0 );
774 if ( x <= mControlPoints.at( 0 ).x() )
775 return std::clamp( mControlPoints.at( 0 ).y(), 0.0, 1.0 );
776 if ( x >= mControlPoints.at( n - 1 ).x() )
777 return std::clamp( mControlPoints.at( n - 1 ).y(), 0.0, 1.0 );
780 QList<QgsPointXY>::const_iterator pointIt = mControlPoints.constBegin();
785 for (
int i = 0; i < n - 1; ++i )
787 if ( x < nextControlPoint.
x() )
790 double h = nextControlPoint.
x() - currentControlPoint.
x();
791 double t = ( x - currentControlPoint.
x() ) / h;
795 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] ), 0.0, 1.0 );
799 if ( pointIt == mControlPoints.constEnd() )
802 currentControlPoint = nextControlPoint;
803 nextControlPoint = *pointIt;
807 return std::clamp( x, 0.0, 1.0 );
816 QVector<double> result;
818 int n = mControlPoints.count();
822 const auto constX = x;
823 for (
double i : constX )
830 QList<QgsPointXY>::const_iterator pointIt = mControlPoints.constBegin();
836 double currentX = x.at( xIndex );
838 while ( currentX <= currentControlPoint.
x() )
840 result << std::clamp( currentControlPoint.
y(), 0.0, 1.0 );
842 currentX = x.at( xIndex );
845 for (
int i = 0; i < n - 1; ++i )
847 while ( currentX < nextControlPoint.
x() )
850 double h = nextControlPoint.
x() - currentControlPoint.
x();
852 double t = ( currentX - currentControlPoint.
x() ) / h;
856 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 );
858 if ( xIndex == x.count() )
861 currentX = x.at( xIndex );
865 if ( pointIt == mControlPoints.constEnd() )
868 currentControlPoint = nextControlPoint;
869 nextControlPoint = *pointIt;
873 while ( xIndex < x.count() )
875 result << std::clamp( nextControlPoint.
y(), 0.0, 1.0 );
884 QString xString = elem.attribute( u
"x"_s );
885 QString yString = elem.attribute( u
"y"_s );
887 QStringList xVals = xString.split(
',' );
888 QStringList yVals = yString.split(
',' );
889 if ( xVals.count() != yVals.count() )
892 QList< QgsPointXY > newPoints;
894 for (
int i = 0; i < xVals.count(); ++i )
896 double x = xVals.at( i ).toDouble( &ok );
899 double y = yVals.at( i ).toDouble( &ok );
912 const auto constMControlPoints = mControlPoints;
913 for (
const QgsPointXY &p : constMControlPoints )
919 transformElem.setAttribute( u
"x"_s, x.join(
',' ) );
920 transformElem.setAttribute( u
"y"_s,
y.join(
',' ) );
927 QVariantMap transformMap;
931 const auto constMControlPoints = mControlPoints;
932 for (
const QgsPointXY &p : constMControlPoints )
938 transformMap.insert( u
"x"_s, x.join(
',' ) );
939 transformMap.insert( u
"y"_s,
y.join(
',' ) );
946 QVariantMap transformMap = transformer.toMap();
948 QString xString = transformMap.value( u
"x"_s ).toString();
949 QString yString = transformMap.value( u
"y"_s ).toString();
951 QStringList xVals = xString.split(
',' );
952 QStringList yVals = yString.split(
',' );
953 if ( xVals.count() != yVals.count() )
956 QList< QgsPointXY > newPoints;
958 for (
int i = 0; i < xVals.count(); ++i )
960 double x = xVals.at( i ).toDouble( &ok );
963 double y = yVals.at( i ).toDouble( &ok );
976void QgsCurveTransform::calcSecondDerivativeArray()
978 int n = mControlPoints.count();
982 delete[] mSecondDerivativeArray;
984 double *matrix =
new double[n * 3];
985 double *result =
new double[n];
990 QList<QgsPointXY>::const_iterator pointIt = mControlPoints.constBegin();
997 for (
int i = 1; i < n - 1; ++i )
999 matrix[i * 3 + 0] = ( pointI.
x() - pointIm1.
x() ) / 6.0;
1000 matrix[i * 3 + 1] = ( pointIp1.
x() - pointIm1.
x() ) / 3.0;
1001 matrix[i * 3 + 2] = ( pointIp1.
x() - pointI.
x() ) / 6.0;
1002 result[i] = ( pointIp1.
y() - pointI.
y() ) / ( pointIp1.
x() - pointI.
x() ) - ( pointI.
y() - pointIm1.
y() ) / ( pointI.
x() - pointIm1.
x() );
1008 if ( pointIt == mControlPoints.constEnd() )
1011 pointIp1 = *pointIt;
1013 matrix[( n - 1 ) * 3 + 0] = 0;
1014 matrix[( n - 1 ) * 3 + 1] = 1;
1015 matrix[( n - 1 ) * 3 + 2] = 0;
1019 for (
int i = 1; i < n; ++i )
1021 double k = matrix[i * 3 + 0] / matrix[( i - 1 ) * 3 + 1];
1022 matrix[i * 3 + 1] -= k * matrix[( i - 1 ) * 3 + 2];
1023 matrix[i * 3 + 0] = 0;
1024 result[i] -= k * result[i - 1];
1027 for (
int i = n - 2; i >= 0; --i )
1029 double k = matrix[i * 3 + 2] / matrix[( i + 1 ) * 3 + 1];
1030 matrix[i * 3 + 1] -= k * matrix[( i + 1 ) * 3 + 0];
1031 matrix[i * 3 + 2] = 0;
1032 result[i] -= k * result[i + 1];
1036 mSecondDerivativeArray =
new double[n];
1037 for (
int i = 0; i < n; ++i )
1039 mSecondDerivativeArray[i] = result[i] / matrix[( i * 3 ) + 1];
Abstract base class for color ramps.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
An expression node which takes its value from a feature's field.
An expression node for expression functions.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
std::shared_ptr< QgsExpressionFunction > function() const
Returns a reference to the node's function.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Handles parsing and evaluation of expressions (formerly called "search strings").
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.
std::shared_ptr< QgsExpressionFunction > SharedFunctionPtr
QVariant evaluate()
Evaluate the feature and return the result.
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
static std::unique_ptr< QgsColorRamp > loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
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).