28  mStrokeWidth = strokeWidth;
 
 
   38  mStrokeColoring = strokeColoring;
 
 
   43  return mStrokeColoring;
 
 
   48  mStrokeWidthUnit = strokeWidthUnit;
 
 
   53  return mStrokeWidthUnit;
 
 
   58  QPainter *painter = context.
painter();
 
   62  QPointF dir = p2 - p1;
 
   63  double length = sqrt( pow( dir.x(), 2 ) + pow( dir.y(), 2 ) );
 
   64  QPointF diru = dir / length;
 
   65  QPointF orthu = QPointF( -diru.y(), diru.x() );
 
   67  QList<double> breakValues;
 
   68  QList<QColor> breakColors;
 
   69  QList<QLinearGradient> gradients;
 
   71  mStrokeColoring.
graduatedColors( valueColor1, valueColor2, breakValues, breakColors, gradients );
 
   74  if ( gradients.isEmpty() && !breakValues.empty() && !breakColors.isEmpty() ) 
 
   76    Q_ASSERT( breakColors.count() == breakValues.count() );
 
   77    for ( 
int i = 0; i < breakValues.count(); ++i )
 
   79      const bool widthIsInverted { valueWidth1 > valueWidth2 };
 
   80      const double value = breakValues.at( i );
 
   82      QPen pen( mSelected ? selectedColor : breakColors.at( i ) );
 
   83      pen.setWidthF( width );
 
   84      pen.setCapStyle( Qt::PenCapStyle::RoundCap );
 
   85      painter->setPen( pen );
 
   86      const QPointF point = p1 + dir * ( value - valueColor1 ) / ( valueColor2 - valueColor1 );
 
   87      painter->drawPoint( point );
 
   92    double width1 = mStrokeWidth.
strokeWidth( valueWidth1 );
 
   93    double width2 = mStrokeWidth.
strokeWidth( valueWidth2 );
 
   95    if ( !std::isnan( width1 ) && !std::isnan( width2 ) ) 
 
   98      QBrush brush( Qt::SolidPattern );
 
  101      startAngle = ( acos( -orthu.x() ) / M_PI ) * 180;
 
  103        startAngle = 360 - startAngle;
 
  105      bool outOfRange1 = std::isnan( width1 );
 
  106      bool outOfRange2 = std::isnan( width2 );
 
  111        QRectF capBox1( p1.x() - width1 / 2, p1.y() - width1 / 2, width1, width1 );
 
  112        brush.setColor( mSelected ? selectedColor : mStrokeColoring.
color( valueColor1 ) );
 
  113        painter->setBrush( brush );
 
  114        pen.setBrush( brush );
 
  115        painter->setPen( pen );
 
  116        painter->drawPie( capBox1, ( startAngle - 1 ) * 16, 182 * 16 );
 
  122        QRectF capBox2( p2.x() - width2 / 2, p2.y() - width2 / 2, width2, width2 );
 
  123        brush.setColor( mSelected ? selectedColor : mStrokeColoring.
color( valueColor2 ) );
 
  124        pen.setBrush( brush );
 
  125        painter->setBrush( brush );
 
  126        painter->setPen( pen );
 
  127        painter->drawPie( capBox2, ( startAngle + 179 ) * 16, 182 * 16 );
 
  130      if ( ( gradients.isEmpty() && breakValues.empty() && breakColors.count() == 1 ) || mSelected ) 
 
  132        double startAdjusting = 0;
 
  134          adjustLine( valueColor1, valueColor1, valueColor2, width1, startAdjusting );
 
  137        double endAdjusting = 0;
 
  139          adjustLine( valueColor2, valueColor1, valueColor2, width2, endAdjusting );
 
  141        QPointF pointStartAdjusted = p1 + dir * startAdjusting;
 
  142        QPointF pointEndAdjusted  = p2 - dir * endAdjusting;
 
  145        double semiWidth1 = width1 / 2;
 
  146        double semiWidth2 = width2 / 2;
 
  148        varLine.append( pointStartAdjusted + orthu * semiWidth1 );
 
  149        varLine.append( pointEndAdjusted + orthu * semiWidth2 );
 
  150        varLine.append( pointEndAdjusted - orthu * semiWidth2 );
 
  151        varLine.append( pointStartAdjusted - orthu * semiWidth1 );
 
  153        QBrush brush( Qt::SolidPattern );
 
  154        brush.setColor( mSelected ? selectedColor : breakColors.first() );
 
  155        painter->setBrush( brush );
 
  156        painter->setPen( pen );
 
  159        pen.setBrush( brush );
 
  161        painter->setPen( pen );
 
  163        painter->drawPolygon( varLine );
 
  166      else if ( !gradients.isEmpty() && !breakValues.isEmpty() && !breakColors.isEmpty() )
 
  168        Q_ASSERT( breakColors.count() == breakValues.count() );
 
  169        Q_ASSERT( breakColors.count() == gradients.count() + 1 );
 
  170        double widthColorVariationValueRatio = ( valueWidth2 - valueWidth1 ) / ( valueColor2 - valueColor1 );
 
  172        for ( 
int i = 0; i < gradients.count(); ++i )
 
  174          double firstValue = breakValues.at( i );
 
  175          double secondValue = breakValues.at( i + 1 );
 
  176          double w1 =  mStrokeWidth.
strokeWidth( widthColorVariationValueRatio * ( firstValue - valueColor1 ) + valueWidth1 );
 
  177          double w2 =  mStrokeWidth.
strokeWidth( widthColorVariationValueRatio * ( secondValue - valueColor1 ) + valueWidth1 );
 
  179          if ( std::isnan( w1 ) && std::isnan( w2 ) )
 
  182          double firstAdjusting = 0;
 
  183          if ( std::isnan( w1 ) )
 
  184            adjustLine( firstValue, valueColor1, valueColor2, w1, firstAdjusting );
 
  187          double secondAdjusting = 0;
 
  188          if ( std::isnan( w2 ) )
 
  189            adjustLine( secondValue, valueColor1, valueColor2, w2, secondAdjusting );
 
  194          QPointF pointStart = p1 + dir * ( firstValue - valueColor1 ) / ( valueColor2 - valueColor1 );
 
  195          QPointF pointEnd = p1 + dir * ( secondValue - valueColor1 ) / ( valueColor2 - valueColor1 );
 
  197          QPointF pointStartAdjusted = pointStart + dir * firstAdjusting;
 
  198          QPointF pointEndAdjusted  = pointEnd - dir * secondAdjusting;
 
  204          varLine.append( pointStartAdjusted + orthu * sw1 );
 
  205          varLine.append( pointEndAdjusted + orthu * sw2 );
 
  206          varLine.append( pointEndAdjusted - orthu * sw2 );
 
  207          varLine.append( pointStartAdjusted - orthu * sw1 );
 
  209          QLinearGradient gradient = gradients.at( i );
 
  210          gradient.setStart( pointStart );
 
  211          gradient.setFinalStop( pointEnd );
 
  212          QBrush brush( gradient );
 
  213          painter->setBrush( brush );
 
  216          pen.setBrush( brush );
 
  218          painter->setPen( pen );
 
  220          painter->drawPolygon( varLine );
 
 
  235  if ( value1 > value2 )
 
  237    std::swap( value1, value2 );
 
  238    std::swap( point1, point2 );
 
 
  254  if ( valueColor1 > valueColor2 )
 
  256    std::swap( valueColor1, valueColor2 );
 
  257    std::swap( valueWidth1, valueWidth2 );
 
  258    std::swap( point1, point2 );
 
 
  269  mSelected = selected;
 
 
  272void QgsInterpolatedLineRenderer::adjustLine( 
const double value, 
const double value1, 
const double value2, 
double &width, 
double &adjusting )
 const 
  276    adjusting = fabs( ( value - mStrokeWidth.
maximumValue() ) / ( value2 - value1 ) );
 
  281    adjusting = fabs( ( value - mStrokeWidth.
minimumValue() ) / ( value2 - value1 ) );
 
  288  return mMinimumValue;
 
 
  294  mNeedUpdateFormula = 
true;
 
 
  299  return mMaximumValue;
 
 
  305  mNeedUpdateFormula = 
true;
 
 
  310  return mMinimumWidth;
 
 
  316  mNeedUpdateFormula = 
true;
 
 
  321  return mMaximumWidth;
 
 
  327  mNeedUpdateFormula = 
true;
 
 
  332  if ( mIsWidthVariable )
 
  334    if ( mNeedUpdateFormula )
 
  335      updateLinearFormula();
 
  337    if ( mUseAbsoluteValue )
 
  338      value = std::fabs( value );
 
  340    if ( value > mMaximumValue )
 
  342      if ( mIgnoreOutOfRange )
 
  343        return std::numeric_limits<double>::quiet_NaN();
 
  345        return mMaximumWidth;
 
  348    if ( value < mMinimumValue )
 
  350      if ( mIgnoreOutOfRange )
 
  351        return std::numeric_limits<double>::quiet_NaN();
 
  353        return mMinimumWidth;
 
  356    return ( value - mMinimumValue ) * mLinearCoef + mMinimumWidth;
 
 
  364  QDomElement elem = doc.createElement( QStringLiteral( 
"mesh-stroke-width" ) );
 
  366  elem.setAttribute( QStringLiteral( 
"width-varying" ), mIsWidthVariable ? 1 : 0 );
 
  367  elem.setAttribute( QStringLiteral( 
"fixed-width" ), mFixedWidth );
 
  368  elem.setAttribute( QStringLiteral( 
"minimum-value" ), mMinimumValue );
 
  369  elem.setAttribute( QStringLiteral( 
"maximum-value" ), mMaximumValue );
 
  370  elem.setAttribute( QStringLiteral( 
"minimum-width" ), mMinimumWidth );
 
  371  elem.setAttribute( QStringLiteral( 
"maximum-width" ), mMaximumWidth );
 
  372  elem.setAttribute( QStringLiteral( 
"ignore-out-of-range" ), mIgnoreOutOfRange ? 1 : 0 );
 
  373  elem.setAttribute( QStringLiteral( 
"use-absolute-value" ), mUseAbsoluteValue ? 1 : 0 );
 
 
  380  mIsWidthVariable = elem.attribute( QStringLiteral( 
"width-varying" ) ).toInt();
 
  381  mFixedWidth = elem.attribute( QStringLiteral( 
"fixed-width" ) ).toDouble();
 
  382  mMinimumValue = elem.attribute( QStringLiteral( 
"minimum-value" ) ).toDouble();
 
  383  mMaximumValue = elem.attribute( QStringLiteral( 
"maximum-value" ) ).toDouble();
 
  384  mMinimumWidth = elem.attribute( QStringLiteral( 
"minimum-width" ) ).toDouble();
 
  385  mMaximumWidth = elem.attribute( QStringLiteral( 
"maximum-width" ) ).toDouble();
 
  386  mIgnoreOutOfRange = elem.attribute( QStringLiteral( 
"ignore-out-of-range" ) ).toInt();
 
  387  mUseAbsoluteValue = elem.attribute( QStringLiteral( 
"use-absolute-value" ) ).toInt();
 
 
  392  return mUseAbsoluteValue;
 
 
  407  return mIgnoreOutOfRange;
 
 
  417  return mIsWidthVariable;
 
 
  422  mIsWidthVariable = isWidthVarying;
 
 
  427  mFixedWidth = fixedWidth;
 
 
  430void QgsInterpolatedLineWidth::updateLinearFormula()
 const 
  433    mLinearCoef = ( mMaximumWidth - mMinimumWidth ) / ( mMaximumValue - mMinimumValue ) ;
 
  436  mNeedUpdateFormula = 
false;
 
  441  mColorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
 
  442  mColorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
 
 
  454  mColorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
 
  455  mColorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
 
 
  469  mSingleColor = 
color;
 
 
  475  if ( mColoringMethod == 
ColorRamp && lSourceColorRamp )
 
  477    if ( mColorRampShader.
isEmpty() )
 
  478      return lSourceColorRamp->
color( 0 );
 
  481    if ( mColorRampShader.
shade( magnitude, &r, &g, &b, &a ) )
 
  482      return QColor( r, g, b, a );
 
  484      return QColor( 0, 0, 0, 0 );
 
 
  494  return mColoringMethod;
 
 
  499  return mColorRampShader;
 
 
  509  QDomElement elem = doc.createElement( QStringLiteral( 
"mesh-stroke-color" ) );
 
  512  elem.setAttribute( QStringLiteral( 
"coloring-method" ), mColoringMethod );
 
  513  elem.appendChild( mColorRampShader.
writeXml( doc ) );
 
 
  520  QDomElement shaderElem = elem.firstChildElement( QStringLiteral( 
"colorrampshader" ) );
 
  521  mColorRampShader.
readXml( shaderElem );
 
  525                      elem.attribute( QStringLiteral( 
"coloring-method" ) ).toInt() );
 
 
  535    breakColors.append( mSingleColor );
 
  542      graduatedColorsInterpolated( value1, value2, breakValues, breakColors, gradients );
 
  545      graduatedColorsDiscrete( value1, value2, breakValues, breakColors, gradients );
 
  548      graduatedColorsExact( value1, value2, breakValues, breakColors, gradients );
 
 
  559QLinearGradient QgsInterpolatedLineColor::makeSimpleLinearGradient( 
const QColor &color1, 
const QColor &color2 )
 const 
  561  QLinearGradient gradient;
 
  562  gradient.setColorAt( 0, color1 );
 
  563  gradient.setColorAt( 1, color2 );
 
  568int QgsInterpolatedLineColor::itemColorIndexInf( 
double value )
 const 
  570  QList<QgsColorRampShader::ColorRampItem> itemList = mColorRampShader.
colorRampItemList();
 
  572  if ( itemList.isEmpty() || itemList.first().value > value )
 
  576    itemList.removeLast(); 
 
  578  if ( value > itemList.last().value )
 
  579    return itemList.count() - 1;
 
  581  int indSup = itemList.count() - 1;
 
  586    if ( abs( indSup - indInf ) <= 1 ) 
 
  589    int newInd = ( indInf + indSup ) / 2;
 
  591    if ( std::isnan( itemList.at( newInd ).value ) )
 
  594    if ( itemList.at( newInd ).value <= value )
 
  601void QgsInterpolatedLineColor::graduatedColorsExact( 
double value1, 
double value2, QList<double> &breakValues, QList<QColor> &breakColors, 
const QList<QLinearGradient> &gradients )
 const 
  604  Q_ASSERT( breakValues.isEmpty() );
 
  605  Q_ASSERT( breakColors.isEmpty() );
 
  606  Q_ASSERT( gradients.isEmpty() );
 
  608  const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
 
  609  if ( itemList.isEmpty() )
 
  612  int index = itemColorIndexInf( value1 );
 
  613  if ( index < 0 || !
qgsDoubleNear( value1, itemList.at( index ).value ) )
 
  619    breakColors.append( itemList.at( index ).color );
 
  623  while ( index < itemList.count() && itemList.at( index ).value <= value2 )
 
  625    breakValues.append( itemList.at( index ).value );
 
  626    breakColors.append( itemList.at( index ).color );
 
  631void QgsInterpolatedLineColor::graduatedColorsInterpolated( 
double value1, 
double value2, QList<double> &breakValues, QList<QColor> &breakColors, QList<QLinearGradient> &gradients )
 const 
  634  Q_ASSERT( breakValues.isEmpty() );
 
  635  Q_ASSERT( breakColors.isEmpty() );
 
  636  Q_ASSERT( gradients.isEmpty() );
 
  639  const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
 
  640  if ( itemList.empty() )
 
  643  if ( itemList.count() == 1 )
 
  645    breakColors.append( itemList.first().color );
 
  649  if ( value2 <= itemList.first().value ) 
 
  651    if ( !mColorRampShader.
clip() )
 
  652      breakColors.append( itemList.first().color ); 
 
  656  if ( value1 > itemList.last().value ) 
 
  658    if ( !mColorRampShader.
clip() )
 
  659      breakColors.append( itemList.last().color ); 
 
  669    if ( mColorRampShader.
shade( value1, &r, &g, &b, &a ) )
 
  670      color = QColor( r, g, b, a );
 
  671    breakColors.append( 
color );
 
  676  int index = itemColorIndexInf( value1 );
 
  679    QColor 
color = itemList.first().color;
 
  680    breakColors.append( 
color );
 
  681    if ( mColorRampShader.
clip() ) 
 
  682      breakValues.append( itemList.first().value );
 
  684      breakValues.append( value1 );
 
  691    if ( mColorRampShader.
shade( value1, &r, &g, &b, &a ) )
 
  692      color = QColor( r, g, b, a );
 
  693    breakValues.append( value1 );
 
  694    breakColors.append( 
color );
 
  699  while ( index <  itemList.count() && itemList.at( index ).value < value2 )
 
  701    QColor color1 = breakColors.last();
 
  702    QColor color2 = itemList.at( index ).color;
 
  703    breakValues.append( itemList.at( index ).value );
 
  704    breakColors.append( color2 );
 
  705    gradients.append( makeSimpleLinearGradient( color1, color2 ) );
 
  710  QColor color1 = breakColors.last();
 
  712  if ( value2 < itemList.last().value )
 
  715    if ( mColorRampShader.
shade( value2, &r, &g, &b, &a ) )
 
  716      color2 = QColor( r, g, b, a );
 
  717    breakValues.append( value2 );
 
  721    color2 = itemList.last().color;
 
  722    if ( mColorRampShader.
clip() )
 
  723      breakValues.append( itemList.last().value );
 
  725      breakValues.append( value2 );
 
  727  breakColors.append( color2 );
 
  728  gradients.append( makeSimpleLinearGradient( color1, color2 ) );
 
  732void QgsInterpolatedLineColor::graduatedColorsDiscrete( 
double value1, 
double value2, QList<double> &breakValues, QList<QColor> &breakColors, QList<QLinearGradient> &gradients )
 const 
  735  Q_ASSERT( breakValues.isEmpty() );
 
  736  Q_ASSERT( breakColors.isEmpty() );
 
  737  Q_ASSERT( gradients.isEmpty() );
 
  739  const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
 
  740  if ( itemList.empty() )
 
  743  if ( itemList.count() == 1 )
 
  745    breakColors.append( itemList.first().color );
 
  749  double lastValue = itemList.at( itemList.count() - 2 ).value;
 
  752  if ( value2 <= itemList.first().value ) 
 
  754    breakColors.append( itemList.first().color ); 
 
  758  if ( value1 > lastValue ) 
 
  760    breakColors.append( itemList.last().color ); 
 
  765  int index = itemColorIndexInf( value1 );
 
  771    breakColors.append( itemList.at( index + 1 ).color );
 
  777    breakValues.append( value1 );
 
  778    breakColors.append( itemList.first().color );
 
  782    QColor 
color = itemList.at( index ).color;
 
  783    breakValues.append( value1 );
 
  784    breakColors.append( 
color );
 
  789  while ( index < ( itemList.count() - 1 ) && itemList.at( index ).value < value2 )
 
  791    QColor 
color = itemList.at( index ).color;
 
  792    breakValues.append( itemList.at( index ).value );
 
  793    breakColors.append( 
color );
 
  794    gradients.append( makeSimpleLinearGradient( 
color, 
color ) );
 
  799  QColor lastColor = itemList.at( index ).color;
 
  800  breakColors.append( lastColor );
 
  801  breakValues.append( value2 );
 
  802  gradients.append( makeSimpleLinearGradient( lastColor, lastColor ) );
 
  826  std::unique_ptr<QgsInterpolatedLineSymbolLayer> symbolLayer;
 
  829  if ( 
properties.contains( QStringLiteral( 
"start_width_expression" ) ) )
 
  831  if ( 
properties.contains( QStringLiteral( 
"end_width_expression" ) ) )
 
  834  if ( 
properties.contains( QStringLiteral( 
"start_color_expression" ) ) )
 
  836  if ( 
properties.contains( QStringLiteral( 
"end_color_expression" ) ) )
 
  839  if ( 
properties.contains( QStringLiteral( 
"line_width" ) ) )
 
  840    symbolLayer->mLineRender.mStrokeWidth.setFixedStrokeWidth( 
properties.value( QStringLiteral( 
"line_width" ) ).toDouble() ) ;
 
  841  if ( 
properties.contains( QStringLiteral( 
"line_width_unit" ) ) )
 
  843  if ( 
properties.contains( QStringLiteral( 
"width_varying_minimum_value" ) ) )
 
  844    symbolLayer->mLineRender.mStrokeWidth.setMinimumValue( 
properties.value( QStringLiteral( 
"width_varying_minimum_value" ) ).toDouble() );
 
  845  if ( 
properties.contains( QStringLiteral( 
"width_varying_maximum_value" ) ) )
 
  846    symbolLayer->mLineRender.mStrokeWidth.setMaximumValue( 
properties.value( QStringLiteral( 
"width_varying_maximum_value" ) ).toDouble() );
 
  847  if ( 
properties.contains( QStringLiteral( 
"width_varying_use_absolute_value" ) ) )
 
  848    symbolLayer->mLineRender.mStrokeWidth.setUseAbsoluteValue( 
properties.value( QStringLiteral( 
"width_varying_use_absolute_value" ) ).toInt() );
 
  849  if ( 
properties.contains( QStringLiteral( 
"width_varying_minimum_width" ) ) )
 
  850    symbolLayer->mLineRender.mStrokeWidth.setMinimumWidth( 
properties.value( QStringLiteral( 
"width_varying_minimum_width" ) ).toDouble() );
 
  851  if ( 
properties.contains( QStringLiteral( 
"width_varying_maximum_width" ) ) )
 
  852    symbolLayer->mLineRender.mStrokeWidth.setMaximumWidth( 
properties.value( QStringLiteral( 
"width_varying_maximum_width" ) ).toDouble() );
 
  853  if ( 
properties.contains( QStringLiteral( 
"width_varying_ignore_out_of_range" ) ) )
 
  854    symbolLayer->mLineRender.mStrokeWidth.setIgnoreOutOfRange( 
properties.value( QStringLiteral( 
"width_varying_ignore_out_of_range" ) ).toInt() );
 
  855  if ( 
properties.contains( QStringLiteral( 
"width_varying_is_variable_width" ) ) )
 
  856    symbolLayer->mLineRender.mStrokeWidth.setIsVariableWidth( 
properties.value( QStringLiteral( 
"width_varying_is_variable_width" ) ).toInt() );
 
  858  if ( 
properties.contains( QStringLiteral( 
"single_color" ) ) )
 
  860  if ( 
properties.contains( QStringLiteral( 
"color_ramp_shader" ) ) )
 
  861    symbolLayer->mLineRender.mStrokeColoring.setColor( createColorRampShaderFromProperties( 
properties.value( QStringLiteral( 
"color_ramp_shader" ) ) ) );
 
  862  if ( 
properties.contains( QStringLiteral( 
"coloring_method" ) ) )
 
  863    symbolLayer->mLineRender.mStrokeColoring.setColoringMethod(
 
  866  return symbolLayer.release();
 
 
  879  props.insert( QStringLiteral( 
"line_width" ), QString::number( mLineRender.mStrokeWidth.
fixedStrokeWidth() ) );
 
  881  props.insert( QStringLiteral( 
"width_varying_minimum_value" ), mLineRender.mStrokeWidth.
minimumValue() );
 
  882  props.insert( QStringLiteral( 
"width_varying_maximum_value" ), mLineRender.mStrokeWidth.
maximumValue() );
 
  883  props.insert( QStringLiteral( 
"width_varying_use_absolute_value" ), mLineRender.mStrokeWidth.
useAbsoluteValue() ? 1 : 0 );
 
  884  props.insert( QStringLiteral( 
"width_varying_minimum_width" ), mLineRender.mStrokeWidth.
minimumWidth() );
 
  885  props.insert( QStringLiteral( 
"width_varying_maximum_width" ), mLineRender.mStrokeWidth.
maximumWidth() );
 
  886  props.insert( QStringLiteral( 
"width_varying_ignore_out_of_range" ), mLineRender.mStrokeWidth.
ignoreOutOfRange() ? 1 : 0 );
 
  887  props.insert( QStringLiteral( 
"width_varying_is_variable_width" ), mLineRender.mStrokeWidth.
isVariableWidth() ? 1 : 0 );
 
  890  props.insert( QStringLiteral( 
"coloring_method" ), mLineRender.mStrokeColoring.
coloringMethod() );
 
  892  props.insert( QStringLiteral( 
"color_ramp_shader" ), colorRampShaderProperties() );
 
 
  906  double totalLength = geometry.
length();
 
  910  double variation = ( max - min ) / totalLength;
 
  913  double lengthFromStart = 0;
 
  914  for ( 
int i = 1; i < points.count(); ++i )
 
  916    QPointF p1 = points.at( i - 1 );
 
  917    QPointF p2 = points.at( i );
 
  919    double v1 = min + variation * lengthFromStart;
 
  920    QPointF vectDist = p2 - p1;
 
  921    lengthFromStart += sqrt( pow( vectDist.x(), 2 ) + pow( vectDist.y(), 2 ) );
 
  922    double v2 = min + variation * lengthFromStart;
 
 
  945  if ( start.isEmpty() )
 
 
  968  mLineRender.mStrokeWidthUnit = strokeWidthUnit;
 
 
  975  mLineRender.mStrokeWidth = interpolatedLineWidth;
 
 
  982  if ( start.isEmpty() )
 
 
 1013QVariant QgsInterpolatedLineSymbolLayer::colorRampShaderProperties()
 const 
 1020  props.insert( QStringLiteral( 
"color_ramp_shader_type" ), 
static_cast< int >( colorRampShader.
colorRampType() ) );
 
 1021  props.insert( QStringLiteral( 
"color_ramp_shader_classification_mode" ), 
static_cast< int >( colorRampShader.
classificationMode() ) );
 
 1022  QVariantList colorRampItemListVariant;
 
 1024  const QList<QgsColorRampShader::ColorRampItem> colorRampItemList = colorRampShader.
colorRampItemList();
 
 1027    QVariantMap itemVar;
 
 1028    itemVar[QStringLiteral( 
"label" )] = item.label;
 
 1030    itemVar[QStringLiteral( 
"value" )] = item.value;
 
 1031    colorRampItemListVariant.append( itemVar );
 
 1033  props.insert( QStringLiteral( 
"color_ramp_shader_items_list" ), colorRampItemListVariant );
 
 1035  props.insert( QStringLiteral( 
"color_ramp_shader_minimum_value" ), colorRampShader.
minimumValue() );
 
 1036  props.insert( QStringLiteral( 
"color_ramp_shader_maximum_value" ), colorRampShader.
maximumValue() );
 
 1037  props.insert( QStringLiteral( 
"color_ramp_shader_value_out_of_range" ), colorRampShader.
clip() ? 1 : 0 );
 
 1038  props.insert( QStringLiteral( 
"color_ramp_shader_label_precision" ), colorRampShader.
labelPrecision() );
 
 1043QgsColorRampShader QgsInterpolatedLineSymbolLayer::createColorRampShaderFromProperties( 
const QVariant &properties )
 
 1047  if ( 
properties.userType() != QMetaType::Type::QVariantMap )
 
 1048    return colorRampShader;
 
 1050  QVariantMap shaderVariantMap = 
properties.toMap();
 
 1052  if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_source" ) ) )
 
 1055  if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_type" ) ) )
 
 1057  if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_classification_mode" ) ) )
 
 1059        shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_classification_mode" ) ).toInt() ) );
 
 1061  if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_items_list" ) ) )
 
 1063    QVariant colorRampItemsVar = shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_items_list" ) );
 
 1064    if ( colorRampItemsVar.userType() == QMetaType::Type::QVariantList )
 
 1066      QVariantList itemVariantList = colorRampItemsVar.toList();
 
 1067      QList<QgsColorRampShader::ColorRampItem> colorRampItemList;
 
 1068      for ( 
const QVariant &itemVar : std::as_const( itemVariantList ) )
 
 1071        if ( itemVar.userType() != QMetaType::Type::QVariantMap )
 
 1073        QVariantMap itemVarMap = itemVar.toMap();
 
 1074        if ( !itemVarMap.contains( QStringLiteral( 
"label" ) ) || !itemVarMap.contains( QStringLiteral( 
"color" ) ) || !itemVarMap.contains( QStringLiteral( 
"value" ) ) )
 
 1077        item.
label = itemVarMap.value( QStringLiteral( 
"label" ) ).toString();
 
 1079        item.
value = itemVarMap.value( QStringLiteral( 
"value" ) ).toDouble();
 
 1081        colorRampItemList.append( item );
 
 1087  if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_minimum_value" ) ) )
 
 1088    colorRampShader.
setMinimumValue( shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_minimum_value" ) ).toDouble() );
 
 1090    colorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
 
 1092  if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_maximum_value" ) ) )
 
 1093    colorRampShader.
setMaximumValue( shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_maximum_value" ) ).toDouble() );
 
 1095    colorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
 
 1097  if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_value_out_of_range" ) ) )
 
 1098    colorRampShader.
setClip( shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_value_out_of_range" ) ).toInt() == 1 );
 
 1099  if ( shaderVariantMap.contains( QStringLiteral( 
"color_ramp_shader_label_precision" ) ) )
 
 1100    colorRampShader.
setLabelPrecision( shaderVariantMap.value( QStringLiteral( 
"color_ramp_shader_label_precision" ) ).toInt() );
 
 1102  return colorRampShader;
 
 1110  mRenderingFeature = 
true;
 
 
 1116  mRenderingFeature = 
false;
 
 1118  if ( mLineParts.empty() )
 
 1121  render( mLineParts, context );
 
 
 1125void QgsInterpolatedLineSymbolLayer::render( 
const QVector< QPolygonF > &parts, 
QgsRenderContext &context )
 
 1127  const double totalLength = std::accumulate( parts.begin(), parts.end(), 0.0, []( 
double total, 
const QPolygonF & part )
 
 1129    return total + QgsSymbolLayerUtils::polylineLength( part );
 
 1135  double startValWidth = 0;
 
 1136  double variationPerMapUnitWidth = 0;
 
 1137  double startValColor = 0;
 
 1138  double variationPerMapUnitColor = 0;
 
 1151    double endValWidth = 0;
 
 1159    variationPerMapUnitWidth = ( endValWidth - startValWidth ) / totalLength;
 
 1171    double endValColor = 0;
 
 1179    variationPerMapUnitColor = ( endValColor - startValColor ) / totalLength;
 
 1182  for ( 
const QPolygonF &poly : parts )
 
 1184    double lengthFromStart = 0;
 
 1185    for ( 
int i = 1; i < poly.count(); ++i )
 
 1187      const QPointF p1 = poly.at( i - 1 );
 
 1188      const QPointF p2 = poly.at( i );
 
 1190      const double v1c = startValColor + variationPerMapUnitColor * lengthFromStart;
 
 1191      const double v1w = startValWidth + variationPerMapUnitWidth * lengthFromStart;
 
 1193      const double v2c = startValColor + variationPerMapUnitColor * lengthFromStart;
 
 1194      const double v2w = startValWidth + variationPerMapUnitWidth * lengthFromStart;
 
 1204  if ( points.empty() )
 
 1207  if ( mRenderingFeature )
 
 1211    mLineParts.append( points );
 
 
@ DisableFeatureClipping
If present, indicates that features should never be clipped to the map extent during rendering.
 
ShaderInterpolationMethod
Color ramp shader interpolation methods.
 
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
 
@ Linear
Interpolates the color between two class breaks linearly.
 
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
 
QFlags< SymbolLayerFlag > SymbolLayerFlags
Symbol layer flags.
 
ShaderClassificationMethod
Color ramp shader classification methods.
 
RenderUnit
Rendering size units.
 
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.
 
Qgis::ShaderClassificationMethod classificationMode() const
Returns the classification mode.
 
Qgis::ShaderInterpolationMethod colorRampType() const
Returns the color ramp interpolation method.
 
bool isEmpty() const
Whether the color ramp contains any items.
 
void setSourceColorRamp(QgsColorRamp *colorramp)
Set the source color ramp.
 
void setClassificationMode(Qgis::ShaderClassificationMethod classificationMode)
Sets the classification mode.
 
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom color map.
 
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 an new RGBA value based on one input value.
 
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
 
void setColorRampType(Qgis::ShaderInterpolationMethod colorRampType)
Sets the color ramp interpolation method.
 
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom color map.
 
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.
 
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.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
static double distance2D(double x1, double y1, double x2, double y2)
Returns the 2D distance between (x1, y1) and (x2, y2).
 
A geometry is the spatial representation of a feature.
 
QPolygonF asQPolygonF() const
Returns contents of the geometry as a QPolygonF.
 
double length() const
Returns the planar, 2-dimensional length of geometry.
 
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...
 
Qgis::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(Qgis::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.
 
QColor color() const override
Returns the "representative" color of the symbol layer.
 
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::RenderUnit widthUnit() const
Returns the width unit.
 
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.
 
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.
 
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...
 
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.
 
void setWidthUnit(Qgis::RenderUnit strokeWidthUnit)
Sets the width unit.
 
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.
 
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
 
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
 
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
 
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.
 
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
 
QPainter * painter()
Returns the destination QPainter for the render operation.
 
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
 
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...
 
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(bool initialize=true)
Returns the default application-wide style.
 
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
 
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
 
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
 
@ LineEndColorValue
End line color for interpolated line renderer (since QGIS 3.22)
 
@ LineStartColorValue
Start line color for interpolated line renderer (since QGIS 3.22)
 
@ LineEndWidthValue
End line width for interpolated line renderer (since QGIS 3.22)
 
@ LineStartWidthValue
Start line width for interpolated line renderer (since QGIS 3.22)
 
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.
 
const QgsLegendPatchShape * patchShape() const
Returns the symbol patch shape, to use if rendering symbol preview icons.
 
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
 
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
 
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
 
#define BUILTIN_UNREACHABLE
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)