26   mStrokeWidth = strokeWidth;
 
   36   mStrokeColoring = strokeColoring;
 
   41   return mStrokeColoring;
 
   46   mStrokeWidthUnit = strokeWidthUnit;
 
   51   return mStrokeWidthUnit;
 
   56   QPainter *painter = context.
painter();
 
   60   QPointF dir = p2 - p1;
 
   61   double length = sqrt( pow( dir.x(), 2 ) + pow( dir.y(), 2 ) );
 
   62   QPointF diru = dir / length;
 
   63   QPointF orthu = QPointF( -diru.y(), diru.x() );
 
   65   QList<double> breakValues;
 
   66   QList<QColor> breakColors;
 
   67   QList<QLinearGradient> gradients;
 
   69   mStrokeColoring.
graduatedColors( valueColor1, valueColor2, breakValues, breakColors, gradients );
 
   72   if ( gradients.isEmpty() && !breakValues.empty() && !breakColors.isEmpty() ) 
 
   74     Q_ASSERT( breakColors.count() == breakValues.count() );
 
   75     for ( 
int i = 0; i < breakValues.count(); ++i )
 
   77       double value = breakValues.at( i );
 
   79       QPen pen( mSelected ? selectedColor : breakColors.at( i ) );
 
   80       pen.setWidthF( width );
 
   81       pen.setCapStyle( Qt::PenCapStyle::RoundCap );
 
   82       painter->setPen( pen );
 
   83       QPointF point = p1 + dir * ( value - valueColor1 ) / ( valueColor2 - valueColor1 );
 
   84       painter->drawPoint( point );
 
   89     double width1 = mStrokeWidth.
strokeWidth( valueWidth1 );
 
   90     double width2 = mStrokeWidth.
strokeWidth( valueWidth2 );
 
   92     if ( !std::isnan( width1 ) && !std::isnan( width2 ) ) 
 
   95       QBrush brush( Qt::SolidPattern );
 
   98       startAngle = ( acos( -orthu.x() ) / M_PI ) * 180;
 
  100         startAngle = 360 - startAngle;
 
  102       bool outOfRange1 = std::isnan( width1 );
 
  103       bool outOfRange2 = std::isnan( width2 );
 
  108         QRectF capBox1( p1.x() - width1 / 2, p1.y() - width1 / 2, width1, width1 );
 
  109         brush.setColor( mSelected ? selectedColor : mStrokeColoring.
color( valueColor1 ) );
 
  110         painter->setBrush( brush );
 
  111         pen.setBrush( brush );
 
  112         painter->setPen( pen );
 
  113         painter->drawPie( capBox1, ( startAngle - 1 ) * 16, 182 * 16 );
 
  119         QRectF capBox2( p2.x() - width2 / 2, p2.y() - width2 / 2, width2, width2 );
 
  120         brush.setColor( mSelected ? selectedColor : mStrokeColoring.
color( valueColor2 ) );
 
  121         pen.setBrush( brush );
 
  122         painter->setBrush( brush );
 
  123         painter->setPen( pen );
 
  124         painter->drawPie( capBox2, ( startAngle + 179 ) * 16, 182 * 16 );
 
  127       if ( ( gradients.isEmpty() && breakValues.empty() && breakColors.count() == 1 ) || mSelected ) 
 
  129         double startAdjusting = 0;
 
  131           adjustLine( valueColor1, valueColor1, valueColor2, width1, startAdjusting );
 
  134         double endAdjusting = 0;
 
  136           adjustLine( valueColor2, valueColor1, valueColor2, width2, endAdjusting );
 
  138         QPointF pointStartAdjusted = p1 + dir * startAdjusting;
 
  139         QPointF pointEndAdjusted  = p2 - dir * endAdjusting;
 
  142         double semiWidth1 = width1 / 2;
 
  143         double semiWidth2 = width2 / 2;
 
  145         varLine.append( pointStartAdjusted + orthu * semiWidth1 );
 
  146         varLine.append( pointEndAdjusted + orthu * semiWidth2 );
 
  147         varLine.append( pointEndAdjusted - orthu * semiWidth2 );
 
  148         varLine.append( pointStartAdjusted - orthu * semiWidth1 );
 
  150         QBrush brush( Qt::SolidPattern );
 
  151         brush.setColor( mSelected ? selectedColor : breakColors.first() );
 
  152         painter->setBrush( brush );
 
  153         painter->setPen( pen );
 
  156         pen.setBrush( brush );
 
  158         painter->setPen( pen );
 
  160         painter->drawPolygon( varLine );
 
  163       else if ( !gradients.isEmpty() && !breakValues.isEmpty() && !breakColors.isEmpty() )
 
  165         Q_ASSERT( breakColors.count() == breakValues.count() );
 
  166         Q_ASSERT( breakColors.count() == gradients.count() + 1 );
 
  167         double widthColorVariationValueRatio = ( valueWidth2 - valueWidth1 ) / ( valueColor2 - valueColor1 );
 
  169         for ( 
int i = 0; i < gradients.count(); ++i )
 
  171           double firstValue = breakValues.at( i );
 
  172           double secondValue = breakValues.at( i + 1 );
 
  173           double w1 =  mStrokeWidth.
strokeWidth( widthColorVariationValueRatio * ( firstValue - valueColor1 ) + valueWidth1 );
 
  174           double w2 =  mStrokeWidth.
strokeWidth( widthColorVariationValueRatio * ( secondValue - valueColor1 ) + valueWidth1 );
 
  176           if ( std::isnan( w1 ) && std::isnan( w2 ) )
 
  179           double firstAdjusting = 0;
 
  180           if ( std::isnan( w1 ) )
 
  181             adjustLine( firstValue, valueColor1, valueColor2, w1, firstAdjusting );
 
  184           double secondAdjusting = 0;
 
  185           if ( std::isnan( w2 ) )
 
  186             adjustLine( secondValue, valueColor1, valueColor2, w2, secondAdjusting );
 
  191           QPointF pointStart = p1 + dir * ( firstValue - valueColor1 ) / ( valueColor2 - valueColor1 );
 
  192           QPointF pointEnd = p1 + dir * ( secondValue - valueColor1 ) / ( valueColor2 - valueColor1 );
 
  194           QPointF pointStartAdjusted = pointStart + dir * firstAdjusting;
 
  195           QPointF pointEndAdjusted  = pointEnd - dir * secondAdjusting;
 
  201           varLine.append( pointStartAdjusted + orthu * sw1 );
 
  202           varLine.append( pointEndAdjusted + orthu * sw2 );
 
  203           varLine.append( pointEndAdjusted - orthu * sw2 );
 
  204           varLine.append( pointStartAdjusted - orthu * sw1 );
 
  206           QLinearGradient gradient = gradients.at( i );
 
  207           gradient.setStart( pointStart );
 
  208           gradient.setFinalStop( pointEnd );
 
  209           QBrush brush( gradient );
 
  210           painter->setBrush( brush );
 
  213           pen.setBrush( brush );
 
  215           painter->setPen( pen );
 
  217           painter->drawPolygon( varLine );
 
  232   if ( value1 > value2 )
 
  234     std::swap( value1, value2 );
 
  235     std::swap( point1, point2 );
 
  251   if ( valueColor1 > valueColor2 )
 
  253     std::swap( valueColor1, valueColor2 );
 
  254     std::swap( valueWidth1, valueWidth2 );
 
  255     std::swap( point1, point2 );
 
  266   mSelected = selected;
 
  269 void QgsInterpolatedLineRenderer::adjustLine( 
const double value, 
const double value1, 
const double value2, 
double &width, 
double &adjusting )
 const 
  273     adjusting = fabs( ( value - mStrokeWidth.
maximumValue() ) / ( value2 - value1 ) );
 
  278     adjusting = fabs( ( value - mStrokeWidth.
minimumValue() ) / ( value2 - value1 ) );
 
  285   return mMinimumValue;
 
  291   mNeedUpdateFormula = 
true;
 
  296   return mMaximumValue;
 
  302   mNeedUpdateFormula = 
true;
 
  307   return mMinimumWidth;
 
  313   mNeedUpdateFormula = 
true;
 
  318   return mMaximumWidth;
 
  324   mNeedUpdateFormula = 
true;
 
  329   if ( mIsWidthVariable )
 
  331     if ( mNeedUpdateFormula )
 
  332       updateLinearFormula();
 
  334     if ( mUseAbsoluteValue )
 
  335       value = std::fabs( value );
 
  337     if ( value > mMaximumValue )
 
  339       if ( mIgnoreOutOfRange )
 
  340         return std::numeric_limits<double>::quiet_NaN();
 
  342         return mMaximumWidth;
 
  345     if ( value < mMinimumValue )
 
  347       if ( mIgnoreOutOfRange )
 
  348         return std::numeric_limits<double>::quiet_NaN();
 
  350         return mMinimumWidth;
 
  353     return ( value - mMinimumValue ) * mLinearCoef + mMinimumWidth;
 
  361   QDomElement elem = doc.createElement( QStringLiteral( 
"mesh-stroke-width" ) );
 
  363   elem.setAttribute( QStringLiteral( 
"width-varying" ), mIsWidthVariable ? 1 : 0 );
 
  364   elem.setAttribute( QStringLiteral( 
"fixed-width" ), mFixedWidth );
 
  365   elem.setAttribute( QStringLiteral( 
"minimum-value" ), mMinimumValue );
 
  366   elem.setAttribute( QStringLiteral( 
"maximum-value" ), mMaximumValue );
 
  367   elem.setAttribute( QStringLiteral( 
"minimum-width" ), mMinimumWidth );
 
  368   elem.setAttribute( QStringLiteral( 
"maximum-width" ), mMaximumWidth );
 
  369   elem.setAttribute( QStringLiteral( 
"ignore-out-of-range" ), mIgnoreOutOfRange ? 1 : 0 );
 
  370   elem.setAttribute( QStringLiteral( 
"use-absolute-value" ), mUseAbsoluteValue ? 1 : 0 );
 
  377   mIsWidthVariable = elem.attribute( QStringLiteral( 
"width-varying" ) ).toInt();
 
  378   mFixedWidth = elem.attribute( QStringLiteral( 
"fixed-width" ) ).toDouble();
 
  379   mMinimumValue = elem.attribute( QStringLiteral( 
"minimum-value" ) ).toDouble();
 
  380   mMaximumValue = elem.attribute( QStringLiteral( 
"maximum-value" ) ).toDouble();
 
  381   mMinimumWidth = elem.attribute( QStringLiteral( 
"minimum-width" ) ).toDouble();
 
  382   mMaximumWidth = elem.attribute( QStringLiteral( 
"maximum-width" ) ).toDouble();
 
  383   mIgnoreOutOfRange = elem.attribute( QStringLiteral( 
"ignore-out-of-range" ) ).toInt();
 
  384   mUseAbsoluteValue = elem.attribute( QStringLiteral( 
"use-absolute-value" ) ).toInt();
 
  389   return mUseAbsoluteValue;
 
  404   return mIgnoreOutOfRange;
 
  414   return mIsWidthVariable;
 
  419   mIsWidthVariable = isWidthVarying;
 
  424   mFixedWidth = fixedWidth;
 
  427 void QgsInterpolatedLineWidth::updateLinearFormula()
 const 
  430     mLinearCoef = ( mMaximumWidth - mMinimumWidth ) / ( mMaximumValue - mMinimumValue ) ;
 
  433   mNeedUpdateFormula = 
false;
 
  438   mColorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
 
  439   mColorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
 
  451   mColorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
 
  452   mColorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
 
  466   mSingleColor = 
color;
 
  472   if ( mColoringMethod == 
ColorRamp && lSourceColorRamp )
 
  474     if ( mColorRampShader.
isEmpty() )
 
  475       return lSourceColorRamp->
color( 0 );
 
  478     if ( mColorRampShader.
shade( magnitude, &r, &g, &b, &a ) )
 
  479       return QColor( r, g, b, a );
 
  481       return QColor( 0, 0, 0, 0 );
 
  491   return mColoringMethod;
 
  496   return mColorRampShader;
 
  506   QDomElement elem = doc.createElement( QStringLiteral( 
"mesh-stroke-color" ) );
 
  509   elem.setAttribute( QStringLiteral( 
"coloring-method" ), mColoringMethod );
 
  510   elem.appendChild( mColorRampShader.
writeXml( doc ) );
 
  517   QDomElement shaderElem = elem.firstChildElement( QStringLiteral( 
"colorrampshader" ) );
 
  518   mColorRampShader.
readXml( shaderElem );
 
  522                       elem.attribute( QStringLiteral( 
"coloring-method" ) ).toInt() );
 
  532     breakColors.append( mSingleColor );
 
  539       graduatedColorsInterpolated( value1, value2, breakValues, breakColors, gradients );
 
  542       graduatedColorsDiscrete( value1, value2, breakValues, breakColors, gradients );
 
  545       graduatedColorsExact( value1, value2, breakValues, breakColors, gradients );
 
  556 QLinearGradient QgsInterpolatedLineColor::makeSimpleLinearGradient( 
const QColor &color1, 
const QColor &color2 )
 const 
  558   QLinearGradient gradient;
 
  559   gradient.setColorAt( 0, color1 );
 
  560   gradient.setColorAt( 1, color2 );
 
  565 int QgsInterpolatedLineColor::itemColorIndexInf( 
double value )
 const 
  567   QList<QgsColorRampShader::ColorRampItem> itemList = mColorRampShader.
colorRampItemList();
 
  569   if ( itemList.isEmpty() || itemList.first().value > value )
 
  573     itemList.removeLast(); 
 
  575   if ( value > itemList.last().value )
 
  576     return itemList.count() - 1;
 
  578   int indSup = itemList.count() - 1;
 
  583     if ( abs( indSup - indInf ) <= 1 ) 
 
  586     int newInd = ( indInf + indSup ) / 2;
 
  588     if ( std::isnan( itemList.at( newInd ).value ) )
 
  591     if ( itemList.at( newInd ).value <= value )
 
  598 void QgsInterpolatedLineColor::graduatedColorsExact( 
double value1, 
double value2, QList<double> &breakValues, QList<QColor> &breakColors, 
const QList<QLinearGradient> &gradients )
 const 
  601   Q_ASSERT( breakValues.isEmpty() );
 
  602   Q_ASSERT( breakColors.isEmpty() );
 
  603   Q_ASSERT( gradients.isEmpty() );
 
  605   const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
 
  606   if ( itemList.isEmpty() )
 
  609   int index = itemColorIndexInf( value1 );
 
  610   if ( index < 0 || !
qgsDoubleNear( value1, itemList.at( index ).value ) )
 
  616     breakColors.append( itemList.at( index ).color );
 
  620   while ( index < itemList.count() && itemList.at( index ).value <= value2 )
 
  622     breakValues.append( itemList.at( index ).value );
 
  623     breakColors.append( itemList.at( index ).color );
 
  628 void QgsInterpolatedLineColor::graduatedColorsInterpolated( 
double value1, 
double value2, QList<double> &breakValues, QList<QColor> &breakColors, QList<QLinearGradient> &gradients )
 const 
  631   Q_ASSERT( breakValues.isEmpty() );
 
  632   Q_ASSERT( breakColors.isEmpty() );
 
  633   Q_ASSERT( gradients.isEmpty() );
 
  636   const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
 
  637   if ( itemList.empty() )
 
  640   if ( itemList.count() == 1 )
 
  642     breakColors.append( itemList.first().color );
 
  646   if ( value2 <= itemList.first().value ) 
 
  648     if ( !mColorRampShader.
clip() )
 
  649       breakColors.append( itemList.first().color ); 
 
  653   if ( value1 > itemList.last().value ) 
 
  655     if ( !mColorRampShader.
clip() )
 
  656       breakColors.append( itemList.last().color ); 
 
  666     if ( mColorRampShader.
shade( value1, &r, &g, &b, &a ) )
 
  667       color = QColor( r, g, b, a );
 
  668     breakColors.append( 
color );
 
  673   int index = itemColorIndexInf( value1 );
 
  676     QColor 
color = itemList.first().color;
 
  677     breakColors.append( 
color );
 
  678     if ( mColorRampShader.
clip() ) 
 
  679       breakValues.append( itemList.first().value );
 
  681       breakValues.append( value1 );
 
  688     if ( mColorRampShader.
shade( value1, &r, &g, &b, &a ) )
 
  689       color = QColor( r, g, b, a );
 
  690     breakValues.append( value1 );
 
  691     breakColors.append( 
color );
 
  696   while ( index <  itemList.count() && itemList.at( index ).value < value2 )
 
  698     QColor color1 = breakColors.last();
 
  699     QColor color2 = itemList.at( index ).color;
 
  700     breakValues.append( itemList.at( index ).value );
 
  701     breakColors.append( color2 );
 
  702     gradients.append( makeSimpleLinearGradient( color1, color2 ) );
 
  707   QColor color1 = breakColors.last();
 
  709   if ( value2 < itemList.last().value )
 
  712     if ( mColorRampShader.
shade( value2, &r, &g, &b, &a ) )
 
  713       color2 = QColor( r, g, b, a );
 
  714     breakValues.append( value2 );
 
  718     color2 = itemList.last().color;
 
  719     if ( mColorRampShader.
clip() )
 
  720       breakValues.append( itemList.last().value );
 
  722       breakValues.append( value2 );
 
  724   breakColors.append( color2 );
 
  725   gradients.append( makeSimpleLinearGradient( color1, color2 ) );
 
  729 void QgsInterpolatedLineColor::graduatedColorsDiscrete( 
double value1, 
double value2, QList<double> &breakValues, QList<QColor> &breakColors, QList<QLinearGradient> &gradients )
 const 
  732   Q_ASSERT( breakValues.isEmpty() );
 
  733   Q_ASSERT( breakColors.isEmpty() );
 
  734   Q_ASSERT( gradients.isEmpty() );
 
  736   const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
 
  737   if ( itemList.empty() )
 
  740   if ( itemList.count() == 1 )
 
  742     breakColors.append( itemList.first().color );
 
  746   double lastValue = itemList.at( itemList.count() - 2 ).value;
 
  749   if ( value2 <= itemList.first().value ) 
 
  751     breakColors.append( itemList.first().color ); 
 
  755   if ( value1 > lastValue ) 
 
  757     breakColors.append( itemList.last().color ); 
 
  762   int index = itemColorIndexInf( value1 );
 
  768     breakColors.append( itemList.at( index + 1 ).color );
 
  774     breakValues.append( value1 );
 
  775     breakColors.append( itemList.first().color );
 
  779     QColor 
color = itemList.at( index ).color;
 
  780     breakValues.append( value1 );
 
  781     breakColors.append( 
color );
 
  786   while ( index < ( itemList.count() - 1 ) && itemList.at( index ).value < value2 )
 
  788     QColor 
color = itemList.at( index ).color;
 
  789     breakValues.append( itemList.at( index ).value );
 
  790     breakColors.append( 
color );
 
  791     gradients.append( makeSimpleLinearGradient( 
color, 
color ) );
 
  796   QColor lastColor = itemList.at( index ).color;
 
  797   breakColors.append( lastColor );
 
  798   breakValues.append( value2 );
 
  799   gradients.append( makeSimpleLinearGradient( lastColor, lastColor ) );
 
  823   std::unique_ptr<QgsInterpolatedLineSymbolLayer> symbolLayer;
 
  826   if ( 
properties.contains( QStringLiteral( 
"start_width_expression" ) ) )
 
  828   if ( 
properties.contains( QStringLiteral( 
"end_width_expression" ) ) )
 
  831   if ( 
properties.contains( QStringLiteral( 
"start_color_expression" ) ) )
 
  833   if ( 
properties.contains( QStringLiteral( 
"end_color_expression" ) ) )
 
  836   if ( 
properties.contains( QStringLiteral( 
"line_width" ) ) )
 
  837     symbolLayer->mLineRender.mStrokeWidth.setFixedStrokeWidth( 
properties.value( QStringLiteral( 
"line_width" ) ).toDouble() ) ;
 
  838   if ( 
properties.contains( QStringLiteral( 
"line_width_unit" ) ) )
 
  840   if ( 
properties.contains( QStringLiteral( 
"width_varying_minimum_value" ) ) )
 
  841     symbolLayer->mLineRender.mStrokeWidth.setMinimumValue( 
properties.value( QStringLiteral( 
"width_varying_minimum_value" ) ).toDouble() );
 
  842   if ( 
properties.contains( QStringLiteral( 
"width_varying_maximum_value" ) ) )
 
  843     symbolLayer->mLineRender.mStrokeWidth.setMaximumValue( 
properties.value( QStringLiteral( 
"width_varying_maximum_value" ) ).toDouble() );
 
  844   if ( 
properties.contains( QStringLiteral( 
"width_varying_use_absolute_value" ) ) )
 
  845     symbolLayer->mLineRender.mStrokeWidth.setUseAbsoluteValue( 
properties.value( QStringLiteral( 
"width_varying_use_absolute_value" ) ).toInt() );
 
  846   if ( 
properties.contains( QStringLiteral( 
"width_varying_minimum_width" ) ) )
 
  847     symbolLayer->mLineRender.mStrokeWidth.setMinimumWidth( 
properties.value( QStringLiteral( 
"width_varying_minimum_width" ) ).toDouble() );
 
  848   if ( 
properties.contains( QStringLiteral( 
"width_varying_maximum_width" ) ) )
 
  849     symbolLayer->mLineRender.mStrokeWidth.setMaximumWidth( 
properties.value( QStringLiteral( 
"width_varying_maximum_width" ) ).toDouble() );
 
  850   if ( 
properties.contains( QStringLiteral( 
"width_varying_ignore_out_of_range" ) ) )
 
  851     symbolLayer->mLineRender.mStrokeWidth.setIgnoreOutOfRange( 
properties.value( QStringLiteral( 
"width_varying_ignore_out_of_range" ) ).toInt() );
 
  852   if ( 
properties.contains( QStringLiteral( 
"width_varying_is_variable_width" ) ) )
 
  853     symbolLayer->mLineRender.mStrokeWidth.setIsVariableWidth( 
properties.value( QStringLiteral( 
"width_varying_is_variable_width" ) ).toInt() );
 
  855   if ( 
properties.contains( QStringLiteral( 
"single_color" ) ) )
 
  857   if ( 
properties.contains( QStringLiteral( 
"color_ramp_shader" ) ) )
 
  858     symbolLayer->mLineRender.mStrokeColoring.setColor( createColorRampShaderFromProperties( 
properties.value( QStringLiteral( 
"color_ramp_shader" ) ) ) );
 
  859   if ( 
properties.contains( QStringLiteral( 
"coloring_method" ) ) )
 
  860     symbolLayer->mLineRender.mStrokeColoring.setColoringMethod(
 
  863   return symbolLayer.release();
 
  876   props.insert( QStringLiteral( 
"line_width" ), QString::number( mLineRender.mStrokeWidth.
fixedStrokeWidth() ) );
 
  878   props.insert( QStringLiteral( 
"width_varying_minimum_value" ), mLineRender.mStrokeWidth.
minimumValue() );
 
  879   props.insert( QStringLiteral( 
"width_varying_maximum_value" ), mLineRender.mStrokeWidth.
maximumValue() );
 
  880   props.insert( QStringLiteral( 
"width_varying_use_absolute_value" ), mLineRender.mStrokeWidth.
useAbsoluteValue() ? 1 : 0 );
 
  881   props.insert( QStringLiteral( 
"width_varying_minimum_width" ), mLineRender.mStrokeWidth.
minimumWidth() );
 
  882   props.insert( QStringLiteral( 
"width_varying_maximum_width" ), mLineRender.mStrokeWidth.
maximumWidth() );
 
  883   props.insert( QStringLiteral( 
"width_varying_ignore_out_of_range" ), mLineRender.mStrokeWidth.
ignoreOutOfRange() ? 1 : 0 );
 
  884   props.insert( QStringLiteral( 
"width_varying_is_variable_width" ), mLineRender.mStrokeWidth.
isVariableWidth() ? 1 : 0 );
 
  887   props.insert( QStringLiteral( 
"coloring_method" ), mLineRender.mStrokeColoring.
coloringMethod() );
 
  889   props.insert( QStringLiteral( 
"color_ramp_shader" ), colorRampShaderProperties() );
 
  903   double totalLength = geometry.
length();
 
  907   double variation = ( max - min ) / totalLength;
 
  910   double lengthFromStart = 0;
 
  911   for ( 
int i = 1; i < points.count(); ++i )
 
  913     QPointF p1 = points.at( i - 1 );
 
  914     QPointF p2 = points.at( i );
 
  916     double v1 = min + variation * lengthFromStart;
 
  917     QPointF vectDist = p2 - p1;
 
  918     lengthFromStart += sqrt( pow( vectDist.x(), 2 ) + pow( vectDist.y(), 2 ) );
 
  919     double v2 = min + variation * lengthFromStart;
 
  930   if ( start.isEmpty() )
 
  953   mLineRender.mStrokeWidthUnit = strokeWidthUnit;
 
  960   mLineRender.mStrokeWidth = interpolatedLineWidth;
 
  967   if ( start.isEmpty() )
 
  998 QVariant QgsInterpolatedLineSymbolLayer::colorRampShaderProperties()
 const 
 1005   props.insert( QStringLiteral( 
"color_ramp_shader_type" ), colorRampShader.
colorRampType() );
 
 1006   props.insert( QStringLiteral( 
"color_ramp_shader_classification_mode" ), colorRampShader.
classificationMode() );
 
 1007   QVariantList colorRampItemListVariant;
 
 1009   const QList<QgsColorRampShader::ColorRampItem> colorRampItemList = colorRampShader.
colorRampItemList();
 
 1012     QVariantMap itemVar;
 
 1013     itemVar[QStringLiteral( 
"label" )] = item.label;
 
 1015     itemVar[QStringLiteral( 
"value" )] = item.value;
 
 1016     colorRampItemListVariant.append( itemVar );
 
 1018   props.insert( QStringLiteral( 
"color_ramp_shader_items_list" ), colorRampItemListVariant );
 
 1020   props.insert( QStringLiteral( 
"color_ramp_shader_minimum_value" ), colorRampShader.
minimumValue() );
 
 1021   props.insert( QStringLiteral( 
"color_ramp_shader_maximum_value" ), colorRampShader.
maximumValue() );
 
 1022   props.insert( QStringLiteral( 
"color_ramp_shader_value_out_of_range" ), colorRampShader.
clip() ? 1 : 0 );
 
 1023   props.insert( QStringLiteral( 
"color_ramp_shader_label_precision" ), colorRampShader.
labelPrecision() );
 
 1028 QgsColorRampShader QgsInterpolatedLineSymbolLayer::createColorRampShaderFromProperties( 
const QVariant &properties )
 
 1033     return colorRampShader;
 
 1035   QVariantMap shaderVariantMap = 
properties.toMap();
 
 1037   if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_source" ) ) )
 
 1040   if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_type" ) ) )
 
 1042   if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_classification_mode" ) ) )
 
 1044         shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_classification_mode" ) ).toInt() ) );
 
 1046   if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_items_list" ) ) )
 
 1048     QVariant colorRampItemsVar = shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_items_list" ) );
 
 1049     if ( colorRampItemsVar.type() == QVariant::List )
 
 1051       QVariantList itemVariantList = colorRampItemsVar.toList();
 
 1052       QList<QgsColorRampShader::ColorRampItem> colorRampItemList;
 
 1053       for ( 
const QVariant &itemVar : std::as_const( itemVariantList ) )
 
 1056         if ( itemVar.type() != QVariant::Map )
 
 1058         QVariantMap itemVarMap = itemVar.toMap();
 
 1059         if ( !itemVarMap.contains( QStringLiteral( 
"label" ) ) || !itemVarMap.contains( QStringLiteral( 
"color" ) ) || !itemVarMap.contains( QStringLiteral( 
"value" ) ) )
 
 1062         item.
label = itemVarMap.value( QStringLiteral( 
"label" ) ).toString();
 
 1064         item.
value = itemVarMap.value( QStringLiteral( 
"value" ) ).toDouble();
 
 1066         colorRampItemList.append( item );
 
 1072   if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_minimum_value" ) ) )
 
 1073     colorRampShader.
setMinimumValue( shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_minimum_value" ) ).toDouble() );
 
 1075     colorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
 
 1077   if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_maximum_value" ) ) )
 
 1078     colorRampShader.
setMaximumValue( shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_maximum_value" ) ).toDouble() );
 
 1080     colorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
 
 1082   if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_value_out_of_range" ) ) )
 
 1083     colorRampShader.
setClip( shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_value_out_of_range" ) ).toInt() == 1 );
 
 1084   if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_label_precision" ) ) )
 
 1085     colorRampShader.
setLabelPrecision( shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_label_precision" ) ).toInt() );
 
 1087   return colorRampShader;
 
 1095   mRenderingFeature = 
true;
 
 1101   mRenderingFeature = 
false;
 
 1103   if ( mLineParts.empty() )
 
 1106   render( mLineParts, context );
 
 1110 void QgsInterpolatedLineSymbolLayer::render( 
const QVector< QPolygonF > &parts, 
QgsRenderContext &context )
 
 1112   const double totalLength = std::accumulate( parts.begin(), parts.end(), 0.0, []( 
double total, 
const QPolygonF & part )
 
 1114     return total + QgsSymbolLayerUtils::polylineLength( part );
 
 1120   double startValWidth = 0;
 
 1121   double variationPerMapUnitWidth = 0;
 
 1122   double startValColor = 0;
 
 1123   double variationPerMapUnitColor = 0;
 
 1136     double endValWidth = 0;
 
 1144     variationPerMapUnitWidth = ( endValWidth - startValWidth ) / totalLength;
 
 1156     double endValColor = 0;
 
 1164     variationPerMapUnitColor = ( endValColor - startValColor ) / totalLength;
 
 1167   for ( 
const QPolygonF &poly : parts )
 
 1169     double lengthFromStart = 0;
 
 1170     for ( 
int i = 1; i < poly.count(); ++i )
 
 1172       const QPointF p1 = poly.at( i - 1 );
 
 1173       const QPointF p2 = poly.at( i );
 
 1175       const double v1c = startValColor + variationPerMapUnitColor * lengthFromStart;
 
 1176       const double v1w = startValWidth + variationPerMapUnitWidth * lengthFromStart;
 
 1177       lengthFromStart += std::sqrt( ( p1.x() - p2.x() ) * ( p1.x() - p2.x() ) + ( p1.y() - p2.y() ) * ( p1.y() - p2.y() ) );
 
 1178       const double v2c = startValColor + variationPerMapUnitColor * lengthFromStart;
 
 1179       const double v2w = startValWidth + variationPerMapUnitWidth * lengthFromStart;
 
 1189   if ( points.empty() )
 
 1192   if ( mRenderingFeature )
 
 1196     mLineParts.append( points );
 
@ DisableFeatureClipping
If present, indicates that features should never be clipped to the map extent during rendering.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom colormap.
ClassificationMode classificationMode() const
Returns the classification mode.
bool isEmpty() const
Whether the color ramp contains any items.
Type colorRampType() const
Returns the color ramp type.
void setSourceColorRamp(QgsColorRamp *colorramp)
Set the source color ramp.
ClassificationMode
Classification modes used to create the color ramp shader.
void setClip(bool clip)
Sets whether the shader should not render values out of range.
bool clip() const
Returns whether the shader will clip values which are out of range.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes configuration to a new DOM element.
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) const override
Generates and new RGB value based on one input value.
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
Type
Supported methods for color interpolation.
@ Interpolated
Interpolates the color between two class breaks linearly.
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
void setClassificationMode(ClassificationMode classificationMode)
Sets classification mode.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom colormap.
void setColorRampType(QgsColorRampShader::Type colorRampType)
Sets the color ramp type.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads configuration from the given DOM element.
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
A geometry is the spatial representation of a feature.
double length() const
Returns the planar, 2-dimensional length of geometry.
QPolygonF asQPolygonF() const SIP_HOLDGIL
Returns contents of the geometry as a QPolygonF.
Class defining color to render mesh datasets.
QgsInterpolatedLineColor::ColoringMethod coloringMethod() const
Returns the coloring method used.
QgsColorRampShader colorRampShader() const
Returns the color ramp shader.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from the given DOM element.
QColor color(double magnitude) const
Returns the color corresponding to the magnitude.
void graduatedColors(double value1, double value2, QList< double > &breakValues, QList< QColor > &breakColors, QList< QLinearGradient > &gradients) const
Returns the break values, graduated colors and the associated gradients between two values.
QgsInterpolatedLineColor()
Default constructor.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a new DOM element.
void setColor(const QgsColorRampShader &colorRampShader)
Sets the color ramp to define the coloring.
QColor singleColor() const
Returns the single color that is used if SingleColor coloring mode is set.
void setColoringMethod(ColoringMethod coloringMethod)
Sets the coloring method used.
ColoringMethod
Defines how the color is defined.
@ ColorRamp
Render with a color ramp.
@ SingleColor
Render with a single color.
void setInterpolatedColor(const QgsInterpolatedLineColor &strokeColoring)
Sets the stroke color used to render.
void renderInDeviceCoordinates(double valueColor1, double valueColor2, double valueWidth1, double valueWidth2, QPointF point1, QPointF point2, QgsRenderContext &context) const
Renders a line in the context between point1 and point2 in device (painter) coordinates with color th...
QgsUnitTypes::RenderUnit widthUnit() const
Returns the unit of the stroke width.
void setInterpolatedWidth(const QgsInterpolatedLineWidth &strokeWidth)
Sets the stroke width used to render.
void setSelected(bool selected)
Sets if the rendering must be done as the element is selected.
void render(double value1, double value2, const QgsPointXY &point1, const QgsPointXY &point2, QgsRenderContext &context) const
Renders a line in the context between point1 and point2 with color and width that vary depending on v...
QgsInterpolatedLineWidth interpolatedLineWidth() const
Returns the stroke width used to render.
QgsInterpolatedLineColor interpolatedColor() const
Returns the stroke color used to render.
void setWidthUnit(QgsUnitTypes::RenderUnit strokeWidthUnit)
Sets the unit of the stroke width.
A symbol layer that represents vector layer line feature as interpolated line The interpolation is do...
Q_DECL_DEPRECATED QString endValueExpressionForWidth() const
Returns the expression related to the end extremity value for width.
Q_DECL_DEPRECATED QString endValueExpressionForColor() const
Returns the expression related to the end extremity value for width for color.
Q_DECL_DEPRECATED void setExpressionsStringForColor(const QString &start, const QString &end)
Sets the expressions (as string) that define the extremety values af the line feature for color.
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
QgsInterpolatedLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
QgsInterpolatedLineColor interpolatedColor() const
Returns the interpolated color used to render the colors of lines, see QgsInterpolatedLineColor.
bool isCompatibleWithSymbol(QgsSymbol *symbol) const override
Returns if the layer can be used below the specified symbol.
Q_DECL_DEPRECATED QString startValueExpressionForColor() const
Returns the epression related to the start extremity value for width for color.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QgsInterpolatedLineSymbolLayer()
Constructor.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
QString layerType() const override
Returns a string that represents this layer type.
void setWidthUnit(QgsUnitTypes::RenderUnit strokeWidthUnit)
Sets the width unit.
Q_DECL_DEPRECATED void setExpressionsStringForWidth(const QString &start, const QString &end)
Sets the expressions (as string) that define the extremety values af the line feature for width.
void setInterpolatedWidth(const QgsInterpolatedLineWidth &interpolatedLineWidth)
Sets the interpolated width used to render the width of lines, see QgsInterpolatedLineWidth.
void setInterpolatedColor(const QgsInterpolatedLineColor &interpolatedLineColor)
Sets the interpolated color used to render the colors of lines, see QgsInterpolatedLineColor.
Q_DECL_DEPRECATED QString startValueExpressionForWidth() const
Returns the epression related to the start extremity value for width.
void drawPreviewIcon(QgsSymbolRenderContext &context, QSize size) override
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsUnitTypes::RenderUnit widthUnit() const
Returns the width unit.
QgsInterpolatedLineWidth interpolatedWidth() const
Returns the interpolated width used to render the width of lines, see QgsInterpolatedLineWidth.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
static QgsSymbolLayer * create(const QVariantMap &properties)
Creates the symbol layer.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Represents a width than can vary depending on values.
void setFixedStrokeWidth(double fixedWidth)
Sets the fixed width.
double strokeWidth(double value) const
Returns the variable width depending on value, if not varying returns the fixed width.
void setUseAbsoluteValue(bool useAbsoluteValue)
Sets whether absolute value are used as input.
double minimumValue() const
Returns the minimum value used to defined the variable width.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from the given DOM element.
void setIgnoreOutOfRange(bool ignoreOutOfRange)
Sets whether the variable width ignores out of range value.
void setMaximumValue(double maximumValue)
Sets the maximum value used to defined the variable width.
bool useAbsoluteValue() const
Returns whether absolute value are used as input.
void setIsVariableWidth(bool isVariableWidth)
Returns whether the width is variable.
void setMinimumValue(double minimumValue)
Sets the minimum value used to defined the variable width.
double maximumWidth() const
Returns the maximum width used to defined the variable width.
void setMaximumWidth(double maximumWidth)
Sets the maximum width used to defined the variable width.
double maximumValue() const
Returns the maximum value used to defined the variable width.
void setMinimumWidth(double minimumWidth)
Sets the minimum width used to defined the variable width.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a new DOM element.
bool ignoreOutOfRange() const
Returns whether the variable width ignores out of range value.
double minimumWidth() const
Returns the minimum width used to defined the variable width.
double fixedStrokeWidth() const
Returns the fixed width.
bool isVariableWidth() const
Returns whether the width is variable.
QgsGeometry geometry() const
Returns the geometry for the patch shape.
Perform transforms between map coordinates and device coordinates.
QgsPointXY transform(const QgsPointXY &p) const
Transforms a point p from map (world) coordinates to device coordinates.
A class to represent a 2D point.
QPointF toQPointF() const
Converts a point to a QPointF.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
A store for object properties.
QString asExpression() const
Returns an expression string representing the state of the property, or an empty string if the proper...
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
double maximumValue() const
Returns the minimum value for the raster shader.
void setLabelPrecision(int labelPrecision)
Sets label precision to labelPrecision.
int labelPrecision() const
Returns label precision.
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
double minimumValue() const
Returns the maximum value for the raster shader.
The class is used as a container of context for various read/write operations on other objects.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QColor selectionColor() const
Returns the color to use when rendering selected features.
Scoped object for saving and restoring a QPainter object's state.
QgsLegendPatchShape defaultPatch(Qgis::SymbolType type, QSizeF size) const
Returns the default legend patch shape for the given symbol type.
static QgsStyle * defaultStyle()
Returns default application-wide style.
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)
@ PropertyLineEndWidthValue
End line width for interpolated line renderer (since QGIS 3.22)
@ PropertyLineEndColorValue
End line color for interpolated line renderer (since QGIS 3.22)
@ PropertyLineStartColorValue
Start line color for interpolated line renderer (since QGIS 3.22)
@ PropertyLineStartWidthValue
Start line width for interpolated line renderer (since QGIS 3.22)
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
QgsPropertyCollection mDataDefinedProperties
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
const QgsLegendPatchShape * patchShape() const
Returns the symbol patch shape, to use if rendering symbol preview icons.
Abstract base class for all rendered symbols.
Qgis::SymbolType type() const
Returns the symbol's type.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
RenderUnit
Rendering size units.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)