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