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;
270void 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;
428void 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 );
557QLinearGradient QgsInterpolatedLineColor::makeSimpleLinearGradient(
const QColor &color1,
const QColor &color2 )
const
559 QLinearGradient gradient;
560 gradient.setColorAt( 0, color1 );
561 gradient.setColorAt( 1, color2 );
566int 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 )
599void 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 );
629void 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 ) );
730void 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() )
1011QVariant 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() );
1041QgsColorRampShader 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 );
1123void 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 );
@ DisableFeatureClipping
If present, indicates that features should never be clipped to the map extent during rendering.
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.
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.
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom colormap.
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...
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.
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.
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()
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.
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)