26 mStrokeWidth = strokeWidth;
36 mStrokeColoring = strokeColoring;
41 return mStrokeColoring;
46 mStrokeWidthUnit = strokeWidthUnit;
51 return mStrokeWidthUnit;
54 void QgsInterpolatedLineRenderer::renderInDeviceCoordinate(
double valueColor1,
double valueColor2,
double valueWidth1,
double valueWidth2,
const QPointF &p1,
const QPointF &p2,
QgsRenderContext &context )
const
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 );
162 else if ( !gradients.isEmpty() && !breakValues.isEmpty() && !breakColors.isEmpty() )
164 Q_ASSERT( breakColors.count() == breakValues.count() );
165 Q_ASSERT( breakColors.count() == gradients.count() + 1 );
166 double widthColorVariationValueRatio = ( valueWidth2 - valueWidth1 ) / ( valueColor2 - valueColor1 );
168 for (
int i = 0; i < gradients.count(); ++i )
170 double firstValue = breakValues.at( i );
171 double secondValue = breakValues.at( i + 1 );
172 double w1 = mStrokeWidth.
strokeWidth( widthColorVariationValueRatio * ( firstValue - valueColor1 ) + valueWidth1 );
173 double w2 = mStrokeWidth.
strokeWidth( widthColorVariationValueRatio * ( secondValue - valueColor1 ) + valueWidth1 );
175 if ( std::isnan( w1 ) && std::isnan( w2 ) )
178 double firstAdjusting = 0;
179 if ( std::isnan( w1 ) )
180 adjustLine( firstValue, valueColor1, valueColor2, w1, firstAdjusting );
183 double secondAdjusting = 0;
184 if ( std::isnan( w2 ) )
185 adjustLine( secondValue, valueColor1, valueColor2, w2, secondAdjusting );
190 QPointF pointStart = p1 + dir * ( firstValue - valueColor1 ) / ( valueColor2 - valueColor1 );
191 QPointF pointEnd = p1 + dir * ( secondValue - valueColor1 ) / ( valueColor2 - valueColor1 );
193 QPointF pointStartAdjusted = pointStart + dir * firstAdjusting;
194 QPointF pointEndAdjusted = pointEnd - dir * secondAdjusting;
200 varLine.append( pointStartAdjusted + orthu * sw1 );
201 varLine.append( pointEndAdjusted + orthu * sw2 );
202 varLine.append( pointEndAdjusted - orthu * sw2 );
203 varLine.append( pointStartAdjusted - orthu * sw1 );
205 QLinearGradient gradient = gradients.at( i );
206 gradient.setStart( pointStart );
207 gradient.setFinalStop( pointEnd );
208 QBrush brush( gradient );
209 painter->setBrush( brush );
212 pen.setBrush( brush );
214 painter->setPen( pen );
216 painter->drawPolygon( varLine );
231 if ( value1 > value2 )
233 std::swap( value1, value2 );
234 std::swap( point1, point2 );
240 renderInDeviceCoordinate( value1, value2, value1, value2, p1, p2, context );
250 if ( valueColor1 > valueColor2 )
252 std::swap( valueColor1, valueColor2 );
253 std::swap( valueWidth1, valueWidth2 );
254 std::swap( point1, point2 );
260 renderInDeviceCoordinate( valueColor1, valueColor2, valueWidth1, valueWidth2, p1, p2, context );
265 mSelected = selected;
268 void QgsInterpolatedLineRenderer::adjustLine(
const double &value,
const double &value1,
const double &value2,
double &width,
double &adjusting )
const
272 adjusting = fabs( ( value - mStrokeWidth.
maximumValue() ) / ( value2 - value1 ) );
277 adjusting = fabs( ( value - mStrokeWidth.
minimumValue() ) / ( value2 - value1 ) );
284 return mMinimumValue;
290 mNeedUpdateFormula =
true;
295 return mMaximumValue;
301 mNeedUpdateFormula =
true;
306 return mMinimumWidth;
312 mNeedUpdateFormula =
true;
317 return mMaximumWidth;
323 mNeedUpdateFormula =
true;
328 if ( mIsWidthVariable )
330 if ( mNeedUpdateFormula )
331 updateLinearFormula();
333 if ( mUseAbsoluteValue )
334 value = std::fabs( value );
336 if ( value > mMaximumValue )
338 if ( mIgnoreOutOfRange )
339 return std::numeric_limits<double>::quiet_NaN();
341 return mMaximumWidth;
344 if ( value < mMinimumValue )
346 if ( mIgnoreOutOfRange )
347 return std::numeric_limits<double>::quiet_NaN();
349 return mMinimumWidth;
352 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 );
380 mIsWidthVariable = elem.attribute( QStringLiteral(
"width-varying" ) ).toInt();
381 mFixedWidth = elem.attribute( QStringLiteral(
"fixed-width" ) ).toDouble();
382 mMinimumValue = elem.attribute( QStringLiteral(
"minimum-value" ) ).toDouble();
383 mMaximumValue = elem.attribute( QStringLiteral(
"maximum-value" ) ).toDouble();
384 mMinimumWidth = elem.attribute( QStringLiteral(
"minimum-width" ) ).toDouble();
385 mMaximumWidth = elem.attribute( QStringLiteral(
"maximum-width" ) ).toDouble();
386 mIgnoreOutOfRange = elem.attribute( QStringLiteral(
"ignore-out-of-range" ) ).toInt();
387 mUseAbsoluteValue = elem.attribute( QStringLiteral(
"use-absolute-value" ) ).toInt();
392 return mUseAbsoluteValue;
407 return mIgnoreOutOfRange;
417 return mIsWidthVariable;
422 mIsWidthVariable = isWidthVarying;
427 mFixedWidth = fixedWidth;
430 void QgsInterpolatedLineWidth::updateLinearFormula()
const
432 if ( mMaximumWidth - mMinimumWidth != 0 )
433 mLinearCoef = ( mMaximumWidth - mMinimumWidth ) / ( mMaximumValue - mMinimumValue ) ;
436 mNeedUpdateFormula =
false;
441 mColorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
442 mColorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
454 mColorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
455 mColorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
469 mSingleColor =
color;
475 if ( mColoringMethod ==
ColorRamp && lSourceColorRamp )
477 if ( mColorRampShader.
isEmpty() )
478 return lSourceColorRamp->
color( 0 );
481 if ( mColorRampShader.
shade( magnitude, &r, &g, &b, &a ) )
482 return QColor( r, g, b, a );
484 return QColor( 0, 0, 0, 0 );
494 return mColoringMethod;
499 return mColorRampShader;
511 QDomElement elem = doc.createElement( QStringLiteral(
"mesh-stroke-color" ) );
514 elem.setAttribute( QStringLiteral(
"coloring-method" ), mColoringMethod );
515 elem.appendChild( mColorRampShader.
writeXml( doc ) );
524 QDomElement shaderElem = elem.firstChildElement( QStringLiteral(
"colorrampshader" ) );
525 mColorRampShader.
readXml( shaderElem );
529 elem.attribute( QStringLiteral(
"coloring-method" ) ).toInt() );
539 breakColors.append( mSingleColor );
546 graduatedColorsInterpolated( value1, value2, breakValues, breakColors, gradients );
549 graduatedColorsDiscrete( value1, value2, breakValues, breakColors, gradients );
552 graduatedColorsExact( value1, value2, breakValues, breakColors, gradients );
563 QLinearGradient QgsInterpolatedLineColor::makeSimpleLinearGradient(
const QColor &color1,
const QColor &color2 )
const
565 QLinearGradient gradient;
566 gradient.setColorAt( 0, color1 );
567 gradient.setColorAt( 1, color2 );
572 int QgsInterpolatedLineColor::itemColorIndexInf(
double value )
const
574 QList<QgsColorRampShader::ColorRampItem> itemList = mColorRampShader.
colorRampItemList();
576 if ( itemList.isEmpty() || itemList.first().value > value )
580 itemList.removeLast();
582 if ( value > itemList.last().value )
583 return itemList.count() - 1;
585 int indSup = itemList.count() - 1;
590 if ( abs( indSup - indInf ) <= 1 )
593 int newInd = ( indInf + indSup ) / 2;
595 if ( itemList.at( newInd ).value == std::numeric_limits<double>::quiet_NaN() )
598 if ( itemList.at( newInd ).value <= value )
605 void QgsInterpolatedLineColor::graduatedColorsExact(
double value1,
double value2, QList<double> &breakValues, QList<QColor> &breakColors, QList<QLinearGradient> &gradients )
const
608 Q_ASSERT( breakValues.isEmpty() );
609 Q_ASSERT( breakColors.isEmpty() );
610 Q_ASSERT( gradients.isEmpty() );
612 const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
613 if ( itemList.isEmpty() )
616 int index = itemColorIndexInf( value1 );
617 if ( index < 0 || !
qgsDoubleNear( value1, itemList.at( index ).value ) )
623 breakColors.append( itemList.at( index ).color );
627 while ( index < itemList.count() && itemList.at( index ).value <= value2 )
629 breakValues.append( itemList.at( index ).value );
630 breakColors.append( itemList.at( index ).color );
635 void QgsInterpolatedLineColor::graduatedColorsInterpolated(
double value1,
double value2, QList<double> &breakValues, QList<QColor> &breakColors, QList<QLinearGradient> &gradients )
const
638 Q_ASSERT( breakValues.isEmpty() );
639 Q_ASSERT( breakColors.isEmpty() );
640 Q_ASSERT( gradients.isEmpty() );
643 const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
644 if ( itemList.empty() )
647 if ( itemList.count() == 1 )
649 breakColors.append( itemList.first().color );
653 if ( value2 <= itemList.first().value )
655 if ( !mColorRampShader.
clip() )
656 breakColors.append( itemList.first().color );
660 if ( value1 > itemList.last().value )
662 if ( !mColorRampShader.
clip() )
663 breakColors.append( itemList.last().color );
673 if ( mColorRampShader.
shade( value1, &r, &g, &b, &a ) )
674 color = QColor( r, g, b, a );
675 breakColors.append(
color );
680 int index = itemColorIndexInf( value1 );
683 QColor
color = itemList.first().color;
684 breakColors.append(
color );
685 if ( mColorRampShader.
clip() )
686 breakValues.append( itemList.first().value );
688 breakValues.append( value1 );
695 if ( mColorRampShader.
shade( value1, &r, &g, &b, &a ) )
696 color = QColor( r, g, b, a );
697 breakValues.append( value1 );
698 breakColors.append(
color );
703 while ( index < itemList.count() && itemList.at( index ).value < value2 )
705 QColor color1 = breakColors.last();
706 QColor color2 = itemList.at( index ).color;
707 breakValues.append( itemList.at( index ).value );
708 breakColors.append( color2 );
709 gradients.append( makeSimpleLinearGradient( color1, color2 ) );
714 QColor color1 = breakColors.last();
716 if ( value2 < itemList.last().value )
719 if ( mColorRampShader.
shade( value2, &r, &g, &b, &a ) )
720 color2 = QColor( r, g, b, a );
721 breakValues.append( value2 );
725 color2 = itemList.last().color;
726 if ( mColorRampShader.
clip() )
727 breakValues.append( itemList.last().value );
729 breakValues.append( value2 );
731 breakColors.append( color2 );
732 gradients.append( makeSimpleLinearGradient( color1, color2 ) );
736 void QgsInterpolatedLineColor::graduatedColorsDiscrete(
double value1,
double value2, QList<double> &breakValues, QList<QColor> &breakColors, QList<QLinearGradient> &gradients )
const
739 Q_ASSERT( breakValues.isEmpty() );
740 Q_ASSERT( breakColors.isEmpty() );
741 Q_ASSERT( gradients.isEmpty() );
743 const QList<QgsColorRampShader::ColorRampItem> &itemList = mColorRampShader.
colorRampItemList();
744 if ( itemList.empty() )
747 if ( itemList.count() == 1 )
749 breakColors.append( itemList.first().color );
753 double lastValue = itemList.at( itemList.count() - 2 ).value;
756 if ( value2 <= itemList.first().value )
758 breakColors.append( itemList.first().color );
762 if ( value1 > lastValue )
764 breakColors.append( itemList.last().color );
769 int index = itemColorIndexInf( value1 );
775 breakColors.append( itemList.at( index + 1 ).color );
781 breakValues.append( value1 );
782 breakColors.append( itemList.first().color );
786 QColor
color = itemList.at( index ).color;
787 breakValues.append( value1 );
788 breakColors.append(
color );
793 while ( index < ( itemList.count() - 1 ) && itemList.at( index ).value < value2 )
795 QColor
color = itemList.at( index ).color;
796 breakValues.append( itemList.at( index ).value );
797 breakColors.append(
color );
798 gradients.append( makeSimpleLinearGradient(
color,
color ) );
803 QColor lastColor = itemList.at( index ).color;
804 breakColors.append( lastColor );
805 breakValues.append( value2 );
806 gradients.append( makeSimpleLinearGradient( lastColor, lastColor ) );
820 if ( mStartWidthAttributeIndex == -1 )
822 mStartWidthExpression.reset(
new QgsExpression( mStartWidthExpressionString ) );
826 if ( mEndWidthAttributeIndex == -1 )
828 mEndWithExpression.reset(
new QgsExpression( mEndWidthExpressionString ) );
832 if ( mStartColorAttributeIndex == -1 )
834 mStartColorExpression.reset(
new QgsExpression( mStartColorExpressionString ) );
838 if ( mEndColorAttributeIndex == -1 )
840 mEndColorExpression.reset(
new QgsExpression( mEndColorExpressionString ) );
847 mStartWidthExpression.reset();
848 mEndWithExpression.reset();
849 mStartColorExpression.reset();
850 mEndColorExpression.reset();
863 std::unique_ptr<QgsInterpolatedLineSymbolLayer> symbolLayer;
866 if (
properties.contains( QStringLiteral(
"start_width_expression" ) ) )
867 symbolLayer->mStartWidthExpressionString =
properties.value( QStringLiteral(
"start_width_expression" ) ).toString();
868 if (
properties.contains( QStringLiteral(
"end_width_expression" ) ) )
869 symbolLayer->mEndWidthExpressionString =
properties.value( QStringLiteral(
"end_width_expression" ) ).toString();
871 if (
properties.contains( QStringLiteral(
"start_color_expression" ) ) )
872 symbolLayer->mStartColorExpressionString =
properties.value( QStringLiteral(
"start_color_expression" ) ).toString();
873 if (
properties.contains( QStringLiteral(
"end_color_expression" ) ) )
874 symbolLayer->mEndColorExpressionString =
properties.value( QStringLiteral(
"end_color_expression" ) ).toString();
876 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
877 symbolLayer->mLineRender.mStrokeWidth.setFixedStrokeWidth(
properties.value( QStringLiteral(
"line_width" ) ).toDouble() ) ;
878 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
880 if (
properties.contains( QStringLiteral(
"width_varying_minimum_value" ) ) )
881 symbolLayer->mLineRender.mStrokeWidth.setMinimumValue(
properties.value( QStringLiteral(
"width_varying_minimum_value" ) ).toDouble() );
882 if (
properties.contains( QStringLiteral(
"width_varying_maximum_value" ) ) )
883 symbolLayer->mLineRender.mStrokeWidth.setMaximumValue(
properties.value( QStringLiteral(
"width_varying_maximum_value" ) ).toDouble() );
884 if (
properties.contains( QStringLiteral(
"width_varying_use_absolute_value" ) ) )
885 symbolLayer->mLineRender.mStrokeWidth.setUseAbsoluteValue(
properties.value( QStringLiteral(
"width_varying_use_absolute_value" ) ).toInt() );
886 if (
properties.contains( QStringLiteral(
"width_varying_minimum_width" ) ) )
887 symbolLayer->mLineRender.mStrokeWidth.setMinimumWidth(
properties.value( QStringLiteral(
"width_varying_minimum_width" ) ).toDouble() );
888 if (
properties.contains( QStringLiteral(
"width_varying_maximum_width" ) ) )
889 symbolLayer->mLineRender.mStrokeWidth.setMaximumWidth(
properties.value( QStringLiteral(
"width_varying_maximum_width" ) ).toDouble() );
890 if (
properties.contains( QStringLiteral(
"width_varying_ignore_out_of_range" ) ) )
891 symbolLayer->mLineRender.mStrokeWidth.setIgnoreOutOfRange(
properties.value( QStringLiteral(
"width_varying_ignore_out_of_range" ) ).toInt() );
892 if (
properties.contains( QStringLiteral(
"width_varying_is_variable_width" ) ) )
893 symbolLayer->mLineRender.mStrokeWidth.setIsVariableWidth(
properties.value( QStringLiteral(
"width_varying_is_variable_width" ) ).toInt() );
895 if (
properties.contains( QStringLiteral(
"single_color" ) ) )
897 if (
properties.contains( QStringLiteral(
"color_ramp_shader" ) ) )
898 symbolLayer->mLineRender.mStrokeColoring.setColor( createColorRampShaderFromProperties(
properties.value( QStringLiteral(
"color_ramp_shader" ) ) ) );
899 if (
properties.contains( QStringLiteral(
"coloring_method" ) ) )
900 symbolLayer->mLineRender.mStrokeColoring.setColoringMethod(
903 return symbolLayer.release();
910 props.insert( QStringLiteral(
"start_width_expression" ), mStartWidthExpressionString );
911 props.insert( QStringLiteral(
"end_width_expression" ), mEndWidthExpressionString );
912 props.insert( QStringLiteral(
"start_color_expression" ), mStartColorExpressionString );
913 props.insert( QStringLiteral(
"end_color_expression" ), mEndColorExpressionString );
916 props.insert( QStringLiteral(
"line_width" ), QString::number( mLineRender.mStrokeWidth.
fixedStrokeWidth() ) );
918 props.insert( QStringLiteral(
"width_varying_minimum_value" ), mLineRender.mStrokeWidth.
minimumValue() );
919 props.insert( QStringLiteral(
"width_varying_maximum_value" ), mLineRender.mStrokeWidth.
maximumValue() );
920 props.insert( QStringLiteral(
"width_varying_use_absolute_value" ), mLineRender.mStrokeWidth.
useAbsoluteValue() ? 1 : 0 );
921 props.insert( QStringLiteral(
"width_varying_minimum_width" ), mLineRender.mStrokeWidth.
minimumWidth() );
922 props.insert( QStringLiteral(
"width_varying_maximum_width" ), mLineRender.mStrokeWidth.
maximumWidth() );
923 props.insert( QStringLiteral(
"width_varying_ignore_out_of_range" ), mLineRender.mStrokeWidth.
ignoreOutOfRange() ? 1 : 0 );
924 props.insert( QStringLiteral(
"width_varying_is_variable_width" ), mLineRender.mStrokeWidth.
isVariableWidth() ? 1 : 0 );
927 props.insert( QStringLiteral(
"coloring_method" ), mLineRender.mStrokeColoring.
coloringMethod() );
929 props.insert( QStringLiteral(
"color_ramp_shader" ), colorRampShaderProperties() );
942 mStartWidthAttributeIndex = -1;
943 mEndWidthAttributeIndex = -1;
944 mStartColorAttributeIndex = -1;
945 mEndColorAttributeIndex = -1;
949 double totalLength = geometry.
length();
950 if ( totalLength == 0 )
953 double variation = ( max - min ) / totalLength;
956 double lengthFromStart = 0;
957 for (
int i = 1; i < points.count(); ++i )
959 QPointF p1 = points.at( i - 1 );
960 QPointF p2 = points.at( i );
962 double v1 = min + variation * lengthFromStart;
963 QPointF vectDist = p2 - p1;
964 lengthFromStart += sqrt( pow( vectDist.x(), 2 ) + pow( vectDist.y(), 2 ) );
965 double v2 = min + variation * lengthFromStart;
966 mLineRender.renderInDeviceCoordinate( v1, v2, v1, v2, p1, p2, context.
renderContext() );
975 mStartWidthExpressionString = start;
976 mEndWidthExpressionString = end;
981 return mStartWidthExpressionString;
986 return mEndWidthExpressionString;
991 mLineRender.mStrokeWidthUnit = strokeWidthUnit;
998 mLineRender.mStrokeWidth = interpolatedLineWidth;
1005 mStartColorExpressionString = start;
1006 mEndColorExpressionString = end;
1011 return mStartColorExpressionString;
1016 return mEndColorExpressionString;
1029 QVariant QgsInterpolatedLineSymbolLayer::colorRampShaderProperties()
const
1036 props.insert( QStringLiteral(
"color_ramp_shader_type" ), colorRampShader.
colorRampType() );
1037 props.insert( QStringLiteral(
"color_ramp_shader_classification_mode" ), colorRampShader.
classificationMode() );
1038 QVariantList colorRampItemListVariant;
1040 const QList<QgsColorRampShader::ColorRampItem> colorRampItemList = colorRampShader.
colorRampItemList();
1043 QVariantMap itemVar;
1044 itemVar[QStringLiteral(
"label" )] = item.label;
1046 itemVar[QStringLiteral(
"value" )] = item.value;
1047 colorRampItemListVariant.append( itemVar );
1049 props.insert( QStringLiteral(
"color_ramp_shader_items_list" ), colorRampItemListVariant );
1051 props.insert( QStringLiteral(
"color_ramp_shader_minimum_value" ), colorRampShader.
minimumValue() );
1052 props.insert( QStringLiteral(
"color_ramp_shader_maximum_value" ), colorRampShader.
maximumValue() );
1053 props.insert( QStringLiteral(
"color_ramp_shader_value_out_of_range" ), colorRampShader.
clip() ? 1 : 0 );
1054 props.insert( QStringLiteral(
"color_ramp_shader_label_precision" ), colorRampShader.
labelPrecision() );
1059 QgsColorRampShader QgsInterpolatedLineSymbolLayer::createColorRampShaderFromProperties(
const QVariant &properties )
1064 return colorRampShader;
1066 QVariantMap shaderVariantMap =
properties.toMap();
1068 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_source" ) ) )
1071 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_type" ) ) )
1073 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_classification_mode" ) ) )
1075 shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_classification_mode" ) ).toInt() ) );
1077 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_items_list" ) ) )
1079 QVariant colorRampItemsVar = shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_items_list" ) );
1080 if ( colorRampItemsVar.type() == QVariant::List )
1082 QVariantList itemVariantList = colorRampItemsVar.toList();
1083 QList<QgsColorRampShader::ColorRampItem> colorRampItemList;
1084 for (
const QVariant &itemVar : std::as_const( itemVariantList ) )
1087 if ( itemVar.type() != QVariant::Map )
1089 QVariantMap itemVarMap = itemVar.toMap();
1090 if ( !itemVarMap.contains( QStringLiteral(
"label" ) ) || !itemVarMap.contains( QStringLiteral(
"color" ) ) || !itemVarMap.contains( QStringLiteral(
"value" ) ) )
1093 item.
label = itemVarMap.value( QStringLiteral(
"label" ) ).toString();
1095 item.
value = itemVarMap.value( QStringLiteral(
"value" ) ).toDouble();
1097 colorRampItemList.append( item );
1103 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_minimum_value" ) ) )
1104 colorRampShader.
setMinimumValue( shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_minimum_value" ) ).toDouble() );
1106 colorRampShader.
setMinimumValue( std::numeric_limits<double>::quiet_NaN() );
1108 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_maximum_value" ) ) )
1109 colorRampShader.
setMaximumValue( shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_maximum_value" ) ).toDouble() );
1111 colorRampShader.
setMaximumValue( std::numeric_limits<double>::quiet_NaN() );
1113 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_value_out_of_range" ) ) )
1114 colorRampShader.
setClip( shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_value_out_of_range" ) ).toInt() == 1 );
1115 if ( shaderVariantMap.contains( QStringLiteral(
"color_ramp_shader_label_precision" ) ) )
1116 colorRampShader.
setLabelPrecision( shaderVariantMap.value( QStringLiteral(
"color_ramp_shader_label_precision" ) ).toInt() );
1118 return colorRampShader;
1138 QVector<QgsPolylineXY> lineStrings;
1140 double startValWidth = 0;
1141 double endValWidth = 0;
1142 double variationPerMapUnitWidth = 0;
1143 double startValColor = 0;
1144 double endValColor = 0;
1145 double variationPerMapUnitColor = 0;
1187 double totalLength = geom.
length();
1189 if ( totalLength == 0 )
1192 QVariant val1WidthVariant;
1193 QVariant val2WidthVariant;
1194 QVariant val1ColorVariant;
1195 QVariant val2ColorVariant;
1200 if ( mStartWidthExpression )
1202 val1WidthVariant = mStartWidthExpression->evaluate( &expressionContext );
1203 ok |= mStartWidthExpression->hasEvalError();
1206 val1WidthVariant = mFeature.
attribute( mStartWidthAttributeIndex );
1208 if ( mEndWithExpression )
1210 val2WidthVariant = mEndWithExpression->evaluate( &expressionContext );
1211 ok |= mEndWithExpression->hasEvalError();
1214 val2WidthVariant = mFeature.
attribute( mEndWidthAttributeIndex );
1219 startValWidth = val1WidthVariant.toDouble( &ok );
1223 endValWidth = val2WidthVariant.toDouble( &ok );
1227 variationPerMapUnitWidth = ( endValWidth - startValWidth ) / totalLength;
1232 if ( mStartColorExpression )
1234 val1ColorVariant = mStartColorExpression->evaluate( &expressionContext );
1235 ok |= mStartColorExpression->hasEvalError();
1238 val1ColorVariant = mFeature.
attribute( mStartColorAttributeIndex );
1240 if ( mEndColorExpression )
1242 val2ColorVariant = mEndColorExpression->evaluate( &expressionContext );
1243 ok |= mEndColorExpression->hasEvalError();
1246 val2ColorVariant = mFeature.
attribute( mEndColorAttributeIndex );
1248 startValColor = val1ColorVariant.toDouble( &ok );
1252 endValColor = val2ColorVariant.toDouble( &ok );
1256 variationPerMapUnitColor = ( endValColor - startValColor ) / totalLength;
1259 for (
const QgsPolylineXY &poly : std::as_const( lineStrings ) )
1261 double lengthFromStart = 0;
1262 for (
int i = 1; i < poly.count(); ++i )
1267 double v1c = startValColor + variationPerMapUnitColor * lengthFromStart;
1268 double v1w = startValWidth + variationPerMapUnitWidth * lengthFromStart;
1269 lengthFromStart += p1.
distance( p2 );
1270 double v2c = startValColor + variationPerMapUnitColor * lengthFromStart;
1271 double v2w = startValWidth + variationPerMapUnitWidth * lengthFromStart;
1272 mLineRender.
render( v1c, v2c, v1w, v2w, p1, p2, renderContext );
1285 QSet<QString> attributes;
1291 attributes << mStartWidthExpressionString;
1292 attributes << mEndWidthExpressionString;
1293 attributes << mStartColorExpressionString;
1294 attributes << mEndColorExpressionString;
1296 QgsExpression testExprStartWidth( mStartWidthExpressionString );
1300 QgsExpression testExprEndWidth( mEndWidthExpressionString );
1304 QgsExpression testExprStartColor( mEndWidthExpressionString );
1308 QgsExpression testExprEndColor( mEndWidthExpressionString );
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.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
double length() const
Returns the planar, 2-dimensional length of geometry.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
QPolygonF asQPolygonF() const SIP_HOLDGIL
Returns contents of the geometry as a QPolygonF.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
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 setColoringMethod(const QgsInterpolatedLineColor::ColoringMethod &coloringMethod)
Sets the coloring method used.
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.
ColoringMethod
Defines how the color is defined.
@ ColorRamp
Render with a color ramp.
@ SingleColor
Render with a single color.
void setWidthUnit(const QgsUnitTypes::RenderUnit &strokeWidthUnit)
Sets the unit of the stroke width.
void setInterpolatedColor(const QgsInterpolatedLineColor &strokeColoring)
Sets the stroke color used to render.
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.
A symbol layer that represents vector layer line feature as interpolated line The interpolation is do...
QString endValueExpressionForWidth() const
Returns the expression related to the end extremity value for width.
QString endValueExpressionForColor() const
Returns the expression related to the end extremity value for width for color.
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.
void setWidthUnit(const QgsUnitTypes::RenderUnit &strokeWidthUnit)
Sets the width unit.
bool isCompatibleWithSymbol(QgsSymbol *symbol) const override
Returns if the layer can be used below the specified symbol.
QString startValueExpressionForColor() const
Returns the epression related to the start extremity value for width for color.
void setExpressionsStringForWidth(QString start, QString end)
Sets the expressions (as string) that define the extremety values af the line feature for width.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
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 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.
QString startValueExpressionForWidth() const
Returns the epression related to the start extremity value for width.
void setExpressionsStringForColor(QString start, QString end)
Sets the expressions (as string) that define the extremety values af the line feature for color.
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
Transform the point p from map (world) coordinates to device coordinates.
A class to represent a 2D point.
double distance(double x, double y) const SIP_HOLDGIL
Returns the distance between this point and a specified x, y coordinate.
QPointF toQPointF() const
Converts a point to a QPointF.
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 ...
QColor selectionColor() const
Returns the color to use when rendering selected features.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
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)
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
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.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.