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 const bool widthIsInverted { valueWidth1 > valueWidth2 };
78 const double value = breakValues.at( i );
80 QPen pen( mSelected ? selectedColor : breakColors.at( i ) );
81 pen.setWidthF( width );
82 pen.setCapStyle( Qt::PenCapStyle::RoundCap );
83 painter->setPen( pen );
84 const QPointF point = p1 + dir * ( value - valueColor1 ) / ( valueColor2 - valueColor1 );
85 painter->drawPoint( point );
90 double width1 = mStrokeWidth.
strokeWidth( valueWidth1 );
91 double width2 = mStrokeWidth.
strokeWidth( valueWidth2 );
93 if ( !std::isnan( width1 ) && !std::isnan( width2 ) )
96 QBrush brush( Qt::SolidPattern );
99 startAngle = ( acos( -orthu.x() ) / M_PI ) * 180;
101 startAngle = 360 - startAngle;
103 bool outOfRange1 = std::isnan( width1 );
104 bool outOfRange2 = std::isnan( width2 );
109 QRectF capBox1( p1.x() - width1 / 2, p1.y() - width1 / 2, width1, width1 );
110 brush.setColor( mSelected ? selectedColor : mStrokeColoring.
color( valueColor1 ) );
111 painter->setBrush( brush );
112 pen.setBrush( brush );
113 painter->setPen( pen );
114 painter->drawPie( capBox1, ( startAngle - 1 ) * 16, 182 * 16 );
120 QRectF capBox2( p2.x() - width2 / 2, p2.y() - width2 / 2, width2, width2 );
121 brush.setColor( mSelected ? selectedColor : mStrokeColoring.
color( valueColor2 ) );
122 pen.setBrush( brush );
123 painter->setBrush( brush );
124 painter->setPen( pen );
125 painter->drawPie( capBox2, ( startAngle + 179 ) * 16, 182 * 16 );
128 if ( ( gradients.isEmpty() && breakValues.empty() && breakColors.count() == 1 ) || mSelected )
130 double startAdjusting = 0;
132 adjustLine( valueColor1, valueColor1, valueColor2, width1, startAdjusting );
135 double endAdjusting = 0;
137 adjustLine( valueColor2, valueColor1, valueColor2, width2, endAdjusting );
139 QPointF pointStartAdjusted = p1 + dir * startAdjusting;
140 QPointF pointEndAdjusted = p2 - dir * endAdjusting;
143 double semiWidth1 = width1 / 2;
144 double semiWidth2 = width2 / 2;
146 varLine.append( pointStartAdjusted + orthu * semiWidth1 );
147 varLine.append( pointEndAdjusted + orthu * semiWidth2 );
148 varLine.append( pointEndAdjusted - orthu * semiWidth2 );
149 varLine.append( pointStartAdjusted - orthu * semiWidth1 );
151 QBrush brush( Qt::SolidPattern );
152 brush.setColor( mSelected ? selectedColor : breakColors.first() );
153 painter->setBrush( brush );
154 painter->setPen( pen );
157 pen.setBrush( brush );
159 painter->setPen( pen );
161 painter->drawPolygon( varLine );
164 else if ( !gradients.isEmpty() && !breakValues.isEmpty() && !breakColors.isEmpty() )
166 Q_ASSERT( breakColors.count() == breakValues.count() );
167 Q_ASSERT( breakColors.count() == gradients.count() + 1 );
168 double widthColorVariationValueRatio = ( valueWidth2 - valueWidth1 ) / ( valueColor2 - valueColor1 );
170 for (
int i = 0; i < gradients.count(); ++i )
172 double firstValue = breakValues.at( i );
173 double secondValue = breakValues.at( i + 1 );
174 double w1 = mStrokeWidth.
strokeWidth( widthColorVariationValueRatio * ( firstValue - valueColor1 ) + valueWidth1 );
175 double w2 = mStrokeWidth.
strokeWidth( widthColorVariationValueRatio * ( secondValue - valueColor1 ) + valueWidth1 );
177 if ( std::isnan( w1 ) && std::isnan( w2 ) )
180 double firstAdjusting = 0;
181 if ( std::isnan( w1 ) )
182 adjustLine( firstValue, valueColor1, valueColor2, w1, firstAdjusting );
185 double secondAdjusting = 0;
186 if ( std::isnan( w2 ) )
187 adjustLine( secondValue, valueColor1, valueColor2, w2, secondAdjusting );
192 QPointF pointStart = p1 + dir * ( firstValue - valueColor1 ) / ( valueColor2 - valueColor1 );
193 QPointF pointEnd = p1 + dir * ( secondValue - valueColor1 ) / ( valueColor2 - valueColor1 );
195 QPointF pointStartAdjusted = pointStart + dir * firstAdjusting;
196 QPointF pointEndAdjusted = pointEnd - dir * secondAdjusting;
202 varLine.append( pointStartAdjusted + orthu * sw1 );
203 varLine.append( pointEndAdjusted + orthu * sw2 );
204 varLine.append( pointEndAdjusted - orthu * sw2 );
205 varLine.append( pointStartAdjusted - orthu * sw1 );
207 QLinearGradient gradient = gradients.at( i );
208 gradient.setStart( pointStart );
209 gradient.setFinalStop( pointEnd );
210 QBrush brush( gradient );
211 painter->setBrush( brush );
214 pen.setBrush( brush );
216 painter->setPen( pen );
218 painter->drawPolygon( varLine );
233 if ( value1 > value2 )
235 std::swap( value1, value2 );
236 std::swap( point1, point2 );
252 if ( valueColor1 > valueColor2 )
254 std::swap( valueColor1, valueColor2 );
255 std::swap( valueWidth1, valueWidth2 );
256 std::swap( point1, point2 );
267 mSelected = selected;
270 void QgsInterpolatedLineRenderer::adjustLine(
const double value,
const double value1,
const double value2,
double &width,
double &adjusting )
const
274 adjusting = fabs( ( value - mStrokeWidth.
maximumValue() ) / ( value2 - value1 ) );
279 adjusting = fabs( ( value - mStrokeWidth.
minimumValue() ) / ( value2 - value1 ) );
286 return mMinimumValue;
292 mNeedUpdateFormula =
true;
297 return mMaximumValue;
303 mNeedUpdateFormula =
true;
308 return mMinimumWidth;
314 mNeedUpdateFormula =
true;
319 return mMaximumWidth;
325 mNeedUpdateFormula =
true;
330 if ( mIsWidthVariable )
332 if ( mNeedUpdateFormula )
333 updateLinearFormula();
335 if ( mUseAbsoluteValue )
336 value = std::fabs( value );
338 if ( value > mMaximumValue )
340 if ( mIgnoreOutOfRange )
341 return std::numeric_limits<double>::quiet_NaN();
343 return mMaximumWidth;
346 if ( value < mMinimumValue )
348 if ( mIgnoreOutOfRange )
349 return std::numeric_limits<double>::quiet_NaN();
351 return mMinimumWidth;
354 return ( value - mMinimumValue ) * mLinearCoef + mMinimumWidth;
362 QDomElement elem = doc.createElement( QStringLiteral(
"mesh-stroke-width" ) );
364 elem.setAttribute( QStringLiteral(
"width-varying" ), mIsWidthVariable ? 1 : 0 );
365 elem.setAttribute( QStringLiteral(
"fixed-width" ), mFixedWidth );
366 elem.setAttribute( QStringLiteral(
"minimum-value" ), mMinimumValue );
367 elem.setAttribute( QStringLiteral(
"maximum-value" ), mMaximumValue );
368 elem.setAttribute( QStringLiteral(
"minimum-width" ), mMinimumWidth );
369 elem.setAttribute( QStringLiteral(
"maximum-width" ), mMaximumWidth );
370 elem.setAttribute( QStringLiteral(
"ignore-out-of-range" ), mIgnoreOutOfRange ? 1 : 0 );
371 elem.setAttribute( QStringLiteral(
"use-absolute-value" ), mUseAbsoluteValue ? 1 : 0 );
378 mIsWidthVariable = elem.attribute( QStringLiteral(
"width-varying" ) ).toInt();
379 mFixedWidth = elem.attribute( QStringLiteral(
"fixed-width" ) ).toDouble();
380 mMinimumValue = elem.attribute( QStringLiteral(
"minimum-value" ) ).toDouble();
381 mMaximumValue = elem.attribute( QStringLiteral(
"maximum-value" ) ).toDouble();
382 mMinimumWidth = elem.attribute( QStringLiteral(
"minimum-width" ) ).toDouble();
383 mMaximumWidth = elem.attribute( QStringLiteral(
"maximum-width" ) ).toDouble();
384 mIgnoreOutOfRange = elem.attribute( QStringLiteral(
"ignore-out-of-range" ) ).toInt();
385 mUseAbsoluteValue = elem.attribute( QStringLiteral(
"use-absolute-value" ) ).toInt();
390 return mUseAbsoluteValue;
405 return mIgnoreOutOfRange;
415 return mIsWidthVariable;
420 mIsWidthVariable = isWidthVarying;
425 mFixedWidth = fixedWidth;
428 void QgsInterpolatedLineWidth::updateLinearFormula()
const
431 mLinearCoef = ( mMaximumWidth - mMinimumWidth ) / ( mMaximumValue - mMinimumValue ) ;
434 mNeedUpdateFormula =
false;
439 mColorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
440 mColorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
452 mColorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
453 mColorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
467 mSingleColor =
color;
473 if ( mColoringMethod ==
ColorRamp && lSourceColorRamp )
475 if ( mColorRampShader.
isEmpty() )
476 return lSourceColorRamp->
color( 0 );
479 if ( mColorRampShader.
shade( magnitude, &r, &g, &b, &a ) )
480 return QColor( r, g, b, a );
482 return QColor( 0, 0, 0, 0 );
492 return mColoringMethod;
497 return mColorRampShader;
507 QDomElement elem = doc.createElement( QStringLiteral(
"mesh-stroke-color" ) );
510 elem.setAttribute( QStringLiteral(
"coloring-method" ), mColoringMethod );
511 elem.appendChild( mColorRampShader.
writeXml( doc ) );
518 QDomElement shaderElem = elem.firstChildElement( QStringLiteral(
"colorrampshader" ) );
519 mColorRampShader.
readXml( shaderElem );
523 elem.attribute( QStringLiteral(
"coloring-method" ) ).toInt() );
533 breakColors.append( mSingleColor );
540 graduatedColorsInterpolated( value1, value2, breakValues, breakColors, gradients );
543 graduatedColorsDiscrete( value1, value2, breakValues, breakColors, gradients );
546 graduatedColorsExact( value1, value2, breakValues, breakColors, gradients );
557 QLinearGradient QgsInterpolatedLineColor::makeSimpleLinearGradient(
const QColor &color1,
const QColor &color2 )
const
559 QLinearGradient gradient;
560 gradient.setColorAt( 0, color1 );
561 gradient.setColorAt( 1, color2 );
566 int QgsInterpolatedLineColor::itemColorIndexInf(
double value )
const
568 QList<QgsColorRampShader::ColorRampItem> itemList = mColorRampShader.
colorRampItemList();
570 if ( itemList.isEmpty() || itemList.first().value > value )
574 itemList.removeLast();
576 if ( value > itemList.last().value )
577 return itemList.count() - 1;
579 int indSup = itemList.count() - 1;
584 if ( abs( indSup - indInf ) <= 1 )
587 int newInd = ( indInf + indSup ) / 2;
589 if ( std::isnan( itemList.at( newInd ).value ) )
592 if ( itemList.at( newInd ).value <= value )
599 void QgsInterpolatedLineColor::graduatedColorsExact(
double value1,
double value2, QList<double> &breakValues, QList<QColor> &breakColors,
const QList<QLinearGradient> &gradients )
const
602 Q_ASSERT( breakValues.isEmpty() );
603 Q_ASSERT( breakColors.isEmpty() );
604 Q_ASSERT( gradients.isEmpty() );
606 const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
607 if ( itemList.isEmpty() )
610 int index = itemColorIndexInf( value1 );
611 if ( index < 0 || !
qgsDoubleNear( value1, itemList.at( index ).value ) )
617 breakColors.append( itemList.at( index ).color );
621 while ( index < itemList.count() && itemList.at( index ).value <= value2 )
623 breakValues.append( itemList.at( index ).value );
624 breakColors.append( itemList.at( index ).color );
629 void QgsInterpolatedLineColor::graduatedColorsInterpolated(
double value1,
double value2, QList<double> &breakValues, QList<QColor> &breakColors, QList<QLinearGradient> &gradients )
const
632 Q_ASSERT( breakValues.isEmpty() );
633 Q_ASSERT( breakColors.isEmpty() );
634 Q_ASSERT( gradients.isEmpty() );
637 const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
638 if ( itemList.empty() )
641 if ( itemList.count() == 1 )
643 breakColors.append( itemList.first().color );
647 if ( value2 <= itemList.first().value )
649 if ( !mColorRampShader.
clip() )
650 breakColors.append( itemList.first().color );
654 if ( value1 > itemList.last().value )
656 if ( !mColorRampShader.
clip() )
657 breakColors.append( itemList.last().color );
667 if ( mColorRampShader.
shade( value1, &r, &g, &b, &a ) )
668 color = QColor( r, g, b, a );
669 breakColors.append(
color );
674 int index = itemColorIndexInf( value1 );
677 QColor
color = itemList.first().color;
678 breakColors.append(
color );
679 if ( mColorRampShader.
clip() )
680 breakValues.append( itemList.first().value );
682 breakValues.append( value1 );
689 if ( mColorRampShader.
shade( value1, &r, &g, &b, &a ) )
690 color = QColor( r, g, b, a );
691 breakValues.append( value1 );
692 breakColors.append(
color );
697 while ( index < itemList.count() && itemList.at( index ).value < value2 )
699 QColor color1 = breakColors.last();
700 QColor color2 = itemList.at( index ).color;
701 breakValues.append( itemList.at( index ).value );
702 breakColors.append( color2 );
703 gradients.append( makeSimpleLinearGradient( color1, color2 ) );
708 QColor color1 = breakColors.last();
710 if ( value2 < itemList.last().value )
713 if ( mColorRampShader.
shade( value2, &r, &g, &b, &a ) )
714 color2 = QColor( r, g, b, a );
715 breakValues.append( value2 );
719 color2 = itemList.last().color;
720 if ( mColorRampShader.
clip() )
721 breakValues.append( itemList.last().value );
723 breakValues.append( value2 );
725 breakColors.append( color2 );
726 gradients.append( makeSimpleLinearGradient( color1, color2 ) );
730 void QgsInterpolatedLineColor::graduatedColorsDiscrete(
double value1,
double value2, QList<double> &breakValues, QList<QColor> &breakColors, QList<QLinearGradient> &gradients )
const
733 Q_ASSERT( breakValues.isEmpty() );
734 Q_ASSERT( breakColors.isEmpty() );
735 Q_ASSERT( gradients.isEmpty() );
737 const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
738 if ( itemList.empty() )
741 if ( itemList.count() == 1 )
743 breakColors.append( itemList.first().color );
747 double lastValue = itemList.at( itemList.count() - 2 ).value;
750 if ( value2 <= itemList.first().value )
752 breakColors.append( itemList.first().color );
756 if ( value1 > lastValue )
758 breakColors.append( itemList.last().color );
763 int index = itemColorIndexInf( value1 );
769 breakColors.append( itemList.at( index + 1 ).color );
775 breakValues.append( value1 );
776 breakColors.append( itemList.first().color );
780 QColor
color = itemList.at( index ).color;
781 breakValues.append( value1 );
782 breakColors.append(
color );
787 while ( index < ( itemList.count() - 1 ) && itemList.at( index ).value < value2 )
789 QColor
color = itemList.at( index ).color;
790 breakValues.append( itemList.at( index ).value );
791 breakColors.append(
color );
792 gradients.append( makeSimpleLinearGradient(
color,
color ) );
797 QColor lastColor = itemList.at( index ).color;
798 breakColors.append( lastColor );
799 breakValues.append( value2 );
800 gradients.append( makeSimpleLinearGradient( lastColor, lastColor ) );
824 std::unique_ptr<QgsInterpolatedLineSymbolLayer> symbolLayer;
827 if (
properties.contains( QStringLiteral(
"start_width_expression" ) ) )
829 if (
properties.contains( QStringLiteral(
"end_width_expression" ) ) )
832 if (
properties.contains( QStringLiteral(
"start_color_expression" ) ) )
834 if (
properties.contains( QStringLiteral(
"end_color_expression" ) ) )
837 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
838 symbolLayer->mLineRender.mStrokeWidth.setFixedStrokeWidth(
properties.value( QStringLiteral(
"line_width" ) ).toDouble() ) ;
839 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
841 if (
properties.contains( QStringLiteral(
"width_varying_minimum_value" ) ) )
842 symbolLayer->mLineRender.mStrokeWidth.setMinimumValue(
properties.value( QStringLiteral(
"width_varying_minimum_value" ) ).toDouble() );
843 if (
properties.contains( QStringLiteral(
"width_varying_maximum_value" ) ) )
844 symbolLayer->mLineRender.mStrokeWidth.setMaximumValue(
properties.value( QStringLiteral(
"width_varying_maximum_value" ) ).toDouble() );
845 if (
properties.contains( QStringLiteral(
"width_varying_use_absolute_value" ) ) )
846 symbolLayer->mLineRender.mStrokeWidth.setUseAbsoluteValue(
properties.value( QStringLiteral(
"width_varying_use_absolute_value" ) ).toInt() );
847 if (
properties.contains( QStringLiteral(
"width_varying_minimum_width" ) ) )
848 symbolLayer->mLineRender.mStrokeWidth.setMinimumWidth(
properties.value( QStringLiteral(
"width_varying_minimum_width" ) ).toDouble() );
849 if (
properties.contains( QStringLiteral(
"width_varying_maximum_width" ) ) )
850 symbolLayer->mLineRender.mStrokeWidth.setMaximumWidth(
properties.value( QStringLiteral(
"width_varying_maximum_width" ) ).toDouble() );
851 if (
properties.contains( QStringLiteral(
"width_varying_ignore_out_of_range" ) ) )
852 symbolLayer->mLineRender.mStrokeWidth.setIgnoreOutOfRange(
properties.value( QStringLiteral(
"width_varying_ignore_out_of_range" ) ).toInt() );
853 if (
properties.contains( QStringLiteral(
"width_varying_is_variable_width" ) ) )
854 symbolLayer->mLineRender.mStrokeWidth.setIsVariableWidth(
properties.value( QStringLiteral(
"width_varying_is_variable_width" ) ).toInt() );
856 if (
properties.contains( QStringLiteral(
"single_color" ) ) )
858 if (
properties.contains( QStringLiteral(
"color_ramp_shader" ) ) )
859 symbolLayer->mLineRender.mStrokeColoring.setColor( createColorRampShaderFromProperties(
properties.value( QStringLiteral(
"color_ramp_shader" ) ) ) );
860 if (
properties.contains( QStringLiteral(
"coloring_method" ) ) )
861 symbolLayer->mLineRender.mStrokeColoring.setColoringMethod(
864 return symbolLayer.release();
877 props.insert( QStringLiteral(
"line_width" ), QString::number( mLineRender.mStrokeWidth.
fixedStrokeWidth() ) );
879 props.insert( QStringLiteral(
"width_varying_minimum_value" ), mLineRender.mStrokeWidth.
minimumValue() );
880 props.insert( QStringLiteral(
"width_varying_maximum_value" ), mLineRender.mStrokeWidth.
maximumValue() );
881 props.insert( QStringLiteral(
"width_varying_use_absolute_value" ), mLineRender.mStrokeWidth.
useAbsoluteValue() ? 1 : 0 );
882 props.insert( QStringLiteral(
"width_varying_minimum_width" ), mLineRender.mStrokeWidth.
minimumWidth() );
883 props.insert( QStringLiteral(
"width_varying_maximum_width" ), mLineRender.mStrokeWidth.
maximumWidth() );
884 props.insert( QStringLiteral(
"width_varying_ignore_out_of_range" ), mLineRender.mStrokeWidth.
ignoreOutOfRange() ? 1 : 0 );
885 props.insert( QStringLiteral(
"width_varying_is_variable_width" ), mLineRender.mStrokeWidth.
isVariableWidth() ? 1 : 0 );
888 props.insert( QStringLiteral(
"coloring_method" ), mLineRender.mStrokeColoring.
coloringMethod() );
890 props.insert( QStringLiteral(
"color_ramp_shader" ), colorRampShaderProperties() );
904 double totalLength = geometry.
length();
908 double variation = ( max - min ) / totalLength;
911 double lengthFromStart = 0;
912 for (
int i = 1; i < points.count(); ++i )
914 QPointF p1 = points.at( i - 1 );
915 QPointF p2 = points.at( i );
917 double v1 = min + variation * lengthFromStart;
918 QPointF vectDist = p2 - p1;
919 lengthFromStart += sqrt( pow( vectDist.x(), 2 ) + pow( vectDist.y(), 2 ) );
920 double v2 = min + variation * lengthFromStart;
943 if ( start.isEmpty() )
966 mLineRender.mStrokeWidthUnit = strokeWidthUnit;
973 mLineRender.mStrokeWidth = interpolatedLineWidth;
980 if ( start.isEmpty() )
1011 QVariant QgsInterpolatedLineSymbolLayer::colorRampShaderProperties()
const
1018 props.insert( QStringLiteral(
"color_ramp_shader_type" ), colorRampShader.
colorRampType() );
1019 props.insert( QStringLiteral(
"color_ramp_shader_classification_mode" ), colorRampShader.
classificationMode() );
1020 QVariantList colorRampItemListVariant;
1022 const QList<QgsColorRampShader::ColorRampItem> colorRampItemList = colorRampShader.
colorRampItemList();
1025 QVariantMap itemVar;
1026 itemVar[QStringLiteral(
"label" )] = item.label;
1028 itemVar[QStringLiteral(
"value" )] = item.value;
1029 colorRampItemListVariant.append( itemVar );
1031 props.insert( QStringLiteral(
"color_ramp_shader_items_list" ), colorRampItemListVariant );
1033 props.insert( QStringLiteral(
"color_ramp_shader_minimum_value" ), colorRampShader.
minimumValue() );
1034 props.insert( QStringLiteral(
"color_ramp_shader_maximum_value" ), colorRampShader.
maximumValue() );
1035 props.insert( QStringLiteral(
"color_ramp_shader_value_out_of_range" ), colorRampShader.
clip() ? 1 : 0 );
1036 props.insert( QStringLiteral(
"color_ramp_shader_label_precision" ), colorRampShader.
labelPrecision() );
1041 QgsColorRampShader QgsInterpolatedLineSymbolLayer::createColorRampShaderFromProperties(
const QVariant &properties )
1046 return colorRampShader;
1048 QVariantMap shaderVariantMap =
properties.toMap();
1050 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_source" ) ) )
1053 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_type" ) ) )
1055 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_classification_mode" ) ) )
1057 shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_classification_mode" ) ).toInt() ) );
1059 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_items_list" ) ) )
1061 QVariant colorRampItemsVar = shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_items_list" ) );
1062 if ( colorRampItemsVar.type() == QVariant::List )
1064 QVariantList itemVariantList = colorRampItemsVar.toList();
1065 QList<QgsColorRampShader::ColorRampItem> colorRampItemList;
1066 for (
const QVariant &itemVar : std::as_const( itemVariantList ) )
1069 if ( itemVar.type() != QVariant::Map )
1071 QVariantMap itemVarMap = itemVar.toMap();
1072 if ( !itemVarMap.contains( QStringLiteral(
"label" ) ) || !itemVarMap.contains( QStringLiteral(
"color" ) ) || !itemVarMap.contains( QStringLiteral(
"value" ) ) )
1075 item.
label = itemVarMap.value( QStringLiteral(
"label" ) ).toString();
1077 item.
value = itemVarMap.value( QStringLiteral(
"value" ) ).toDouble();
1079 colorRampItemList.append( item );
1085 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_minimum_value" ) ) )
1086 colorRampShader.
setMinimumValue( shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_minimum_value" ) ).toDouble() );
1088 colorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
1090 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_maximum_value" ) ) )
1091 colorRampShader.
setMaximumValue( shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_maximum_value" ) ).toDouble() );
1093 colorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
1095 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_value_out_of_range" ) ) )
1096 colorRampShader.
setClip( shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_value_out_of_range" ) ).toInt() == 1 );
1097 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_label_precision" ) ) )
1098 colorRampShader.
setLabelPrecision( shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_label_precision" ) ).toInt() );
1100 return colorRampShader;
1108 mRenderingFeature =
true;
1114 mRenderingFeature =
false;
1116 if ( mLineParts.empty() )
1119 render( mLineParts, context );
1123 void QgsInterpolatedLineSymbolLayer::render(
const QVector< QPolygonF > &parts,
QgsRenderContext &context )
1125 const double totalLength = std::accumulate( parts.begin(), parts.end(), 0.0, [](
double total,
const QPolygonF & part )
1127 return total + QgsSymbolLayerUtils::polylineLength( part );
1133 double startValWidth = 0;
1134 double variationPerMapUnitWidth = 0;
1135 double startValColor = 0;
1136 double variationPerMapUnitColor = 0;
1149 double endValWidth = 0;
1157 variationPerMapUnitWidth = ( endValWidth - startValWidth ) / totalLength;
1169 double endValColor = 0;
1177 variationPerMapUnitColor = ( endValColor - startValColor ) / totalLength;
1180 for (
const QPolygonF &poly : parts )
1182 double lengthFromStart = 0;
1183 for (
int i = 1; i < poly.count(); ++i )
1185 const QPointF p1 = poly.at( i - 1 );
1186 const QPointF p2 = poly.at( i );
1188 const double v1c = startValColor + variationPerMapUnitColor * lengthFromStart;
1189 const double v1w = startValWidth + variationPerMapUnitWidth * lengthFromStart;
1190 lengthFromStart += std::sqrt( ( p1.x() - p2.x() ) * ( p1.x() - p2.x() ) + ( p1.y() - p2.y() ) * ( p1.y() - p2.y() ) );
1191 const double v2c = startValColor + variationPerMapUnitColor * lengthFromStart;
1192 const double v2w = startValWidth + variationPerMapUnitWidth * lengthFromStart;
1202 if ( points.empty() )
1205 if ( mRenderingFeature )
1209 mLineParts.append( points );