38#include <QDomDocument>
44 : mPenStyle( penStyle )
48 mCustomDashVector << 5 << 2;
58 mCustomDashPatternUnit = unit;
59 mDashPatternOffsetUnit = unit;
60 mTrimDistanceStartUnit = unit;
61 mTrimDistanceEndUnit = unit;
85 mCustomDashPatternMapUnitScale = scale;
105 if ( props.contains( QStringLiteral(
"line_color" ) ) )
109 else if ( props.contains( QStringLiteral(
"outline_color" ) ) )
113 else if ( props.contains( QStringLiteral(
"color" ) ) )
118 if ( props.contains( QStringLiteral(
"line_width" ) ) )
120 width = props[QStringLiteral(
"line_width" )].toDouble();
122 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
124 width = props[QStringLiteral(
"outline_width" )].toDouble();
126 else if ( props.contains( QStringLiteral(
"width" ) ) )
129 width = props[QStringLiteral(
"width" )].toDouble();
131 if ( props.contains( QStringLiteral(
"line_style" ) ) )
135 else if ( props.contains( QStringLiteral(
"outline_style" ) ) )
139 else if ( props.contains( QStringLiteral(
"penstyle" ) ) )
145 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
149 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
153 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
158 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
160 if ( props.contains( QStringLiteral(
"offset" ) ) )
161 l->
setOffset( props[QStringLiteral(
"offset" )].toDouble() );
162 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
164 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
166 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
168 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
171 if ( props.contains( QStringLiteral(
"use_custom_dash" ) ) )
175 if ( props.contains( QStringLiteral(
"customdash" ) ) )
179 if ( props.contains( QStringLiteral(
"customdash_unit" ) ) )
183 if ( props.contains( QStringLiteral(
"customdash_map_unit_scale" ) ) )
188 if ( props.contains( QStringLiteral(
"draw_inside_polygon" ) ) )
193 if ( props.contains( QStringLiteral(
"ring_filter" ) ) )
198 if ( props.contains( QStringLiteral(
"dash_pattern_offset" ) ) )
200 if ( props.contains( QStringLiteral(
"dash_pattern_offset_unit" ) ) )
202 if ( props.contains( QStringLiteral(
"dash_pattern_offset_map_unit_scale" ) ) )
205 if ( props.contains( QStringLiteral(
"trim_distance_start" ) ) )
207 if ( props.contains( QStringLiteral(
"trim_distance_start_unit" ) ) )
209 if ( props.contains( QStringLiteral(
"trim_distance_start_map_unit_scale" ) ) )
211 if ( props.contains( QStringLiteral(
"trim_distance_end" ) ) )
213 if ( props.contains( QStringLiteral(
"trim_distance_end_unit" ) ) )
215 if ( props.contains( QStringLiteral(
"trim_distance_end_map_unit_scale" ) ) )
218 if ( props.contains( QStringLiteral(
"align_dash_pattern" ) ) )
221 if ( props.contains( QStringLiteral(
"tweak_dash_pattern_on_corners" ) ) )
231 return QStringLiteral(
"SimpleLine" );
243 mPen.setColor( penColor );
245 mPen.setWidthF( scaledWidth );
249 const double dashWidthDiv = std::max( 1.0, scaledWidth );
250 if ( mUseCustomDashPattern )
252 mPen.setStyle( Qt::CustomDashLine );
256 QVector<qreal> scaledVector;
257 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
258 for ( ; it != mCustomDashVector.constEnd(); ++it )
263 mPen.setDashPattern( scaledVector );
267 mPen.setStyle( mPenStyle );
270 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
275 mPen.setJoinStyle( mPenJoinStyle );
276 mPen.setCapStyle( mPenCapStyle );
281 selColor.setAlphaF( context.
opacity() );
282 mSelPen.setColor( selColor );
299 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
306 if ( mDrawInsidePolygon )
314 if ( mDrawInsidePolygon )
317 QPainterPath clipPath;
318 clipPath.addPolygon( points );
323 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
325 QPolygonF ring = *it;
326 clipPath.addPolygon( ring );
331 p->setClipPath( clipPath, Qt::IntersectClip );
354 for (
const QPolygonF &ring : std::as_const( *rings ) )
370 if ( mDrawInsidePolygon )
386 QPolygonF points = pts;
388 double startTrim = mTrimDistanceStart;
394 double endTrim = mTrimDistanceEnd;
401 double totalLength = -1;
405 startTrim = startTrim * 0.01 * totalLength;
413 if ( totalLength < 0 )
415 endTrim = endTrim * 0.01 * totalLength;
428 mPen.setColor( penColor );
431 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
434 const QPen pen = useSelectedColor ? mSelPen : mPen;
436 if ( !pen.dashPattern().isEmpty() )
439 const QVector<double> pattern = pen.dashPattern();
440 bool foundNonNull =
false;
441 for (
int i = 0; i < pattern.size(); ++i )
453 p->setBrush( Qt::NoBrush );
456 std::unique_ptr< QgsScopedQPainterState > painterState;
457 if ( points.size() <= 2 &&
460 ( p->renderHints() & QPainter::Antialiasing ) )
462 painterState = std::make_unique< QgsScopedQPainterState >( p );
463 p->setRenderHint( QPainter::Antialiasing,
false );
466 const bool applyPatternTweaks = mAlignDashPattern
467 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
468 && pen.dashOffset() == 0;
472 if ( applyPatternTweaks )
474 drawPathWithDashPatternTweaks( p, points, pen );
480 path.addPolygon( points );
495 for (
const QPolygonF &part : mline )
497 if ( applyPatternTweaks )
499 drawPathWithDashPatternTweaks( p, part, pen );
505 path.addPolygon( part );
516 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
522 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
525 map[QStringLiteral(
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
529 map[QStringLiteral(
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
532 map[QStringLiteral(
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
535 map[QStringLiteral(
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
538 map[QStringLiteral(
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
539 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
540 map[QStringLiteral(
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
541 map[QStringLiteral(
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
580 if ( mPenStyle == Qt::NoPen )
583 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
584 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
585 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
586 element.appendChild( symbolizerElem );
592 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
593 symbolizerElem.appendChild( strokeElem );
595 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
604 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
607 symbolizerElem.appendChild( perpOffsetElem );
613 if ( mUseCustomDashPattern )
616 mPen.color(), mPenJoinStyle,
617 mPenCapStyle,
mOffset, &mCustomDashVector );
630 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
631 if ( strokeElem.isNull() )
648 QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
649 if ( !perpOffsetElem.isNull() )
652 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
657 double scaleFactor = 1.0;
658 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
673void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
679 bool hasStrokeWidthExpression =
false;
686 pen.setWidthF( scaledWidth );
687 selPen.setWidthF( scaledWidth );
688 hasStrokeWidthExpression =
true;
697 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
698 pen.setColor( penColor );
712 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
716 QVector<qreal> dashVector;
720 QStringList dashList = exprVal.toString().split(
';' );
721 QStringList::const_iterator dashIt = dashList.constBegin();
722 for ( ; dashIt != dashList.constEnd(); ++dashIt )
726 pen.setDashPattern( dashVector );
733 QVector<qreal> scaledVector;
734 for (
double v : std::as_const( mCustomDashVector ) )
739 mPen.setDashPattern( scaledVector );
743 double patternOffset = mDashPatternOffset;
779void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
781 if ( pen.dashPattern().empty() || points.size() < 2 )
784 if ( pen.widthF() <= 1.0 )
786 pen.setWidthF( 1.0001 );
789 QVector< qreal > sourcePattern = pen.dashPattern();
790 const double dashWidthDiv = pen.widthF();
792 for (
int i = 0; i < sourcePattern.size(); ++ i )
793 sourcePattern[i] *= pen.widthF();
795 QVector< qreal > buffer;
796 QPolygonF bufferedPoints;
797 QPolygonF previousSegmentBuffer;
802 auto ptIt = points.constBegin();
803 double totalBufferLength = 0;
804 int patternIndex = 0;
805 double currentRemainingDashLength = 0;
806 double currentRemainingGapLength = 0;
808 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
810 QVector< qreal > result;
811 result.reserve( buffer.size() );
812 for (
auto it = buffer.begin(); it != buffer.end(); )
816 while ( dash == 0 && !result.empty() )
818 result.last() += gap;
820 if ( it == buffer.end() )
825 while ( gap == 0 && it != buffer.end() )
830 result << dash << gap;
835 double currentBufferLineLength = 0;
836 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
837 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
839 if ( buffer.empty() || bufferedPoints.size() < 2 )
844 if ( currentRemainingDashLength )
847 buffer << currentRemainingDashLength << 0.0;
848 totalBufferLength += currentRemainingDashLength;
850 QVector< qreal > compressed = compressPattern( buffer );
851 if ( !currentRemainingDashLength )
854 totalBufferLength -= compressed.last();
855 compressed.last() = 0;
859 const double scaleFactor = currentBufferLineLength / totalBufferLength;
861 bool shouldFlushPreviousSegmentBuffer =
false;
863 if ( !previousSegmentBuffer.empty() )
867 if ( !firstDashSubstring.empty() )
873 compressed = compressed.mid( 2 );
874 shouldFlushPreviousSegmentBuffer = !compressed.empty();
877 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
879 QPen adjustedPen = pen;
880 adjustedPen.setStyle( Qt::SolidLine );
881 painter->setPen( adjustedPen );
883 path.addPolygon( previousSegmentBuffer );
884 painter->drawPath( path );
885 previousSegmentBuffer.clear();
888 double finalDash = 0;
895 if ( !compressed.empty() )
897 finalDash = compressed.at( compressed.size() - 2 );
898 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
900 const QPolygonF thisPoints = bufferedPoints;
906 previousSegmentBuffer << bufferedPoints;
910 currentBufferLineLength = 0;
911 currentRemainingDashLength = 0;
912 currentRemainingGapLength = 0;
913 totalBufferLength = 0;
916 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
918 QPen adjustedPen = pen;
919 if ( !compressed.empty() )
922 compressed = compressed.mid( 0, 32 );
923 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
924 adjustedPen.setDashPattern( compressed );
928 adjustedPen.setStyle( Qt::SolidLine );
931 painter->setPen( adjustedPen );
933 path.addPolygon( bufferedPoints );
934 painter->drawPath( path );
937 bufferedPoints.clear();
943 bufferedPoints << p2;
944 for ( ; ptIt != points.constEnd(); ++ptIt )
952 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
953 currentBufferLineLength += remainingSegmentDistance;
957 if ( currentRemainingDashLength > 0 )
960 if ( remainingSegmentDistance >= currentRemainingDashLength )
963 buffer << currentRemainingDashLength << 0.0;
964 totalBufferLength += currentRemainingDashLength;
965 remainingSegmentDistance -= currentRemainingDashLength;
967 currentRemainingDashLength = 0.0;
968 currentRemainingGapLength = sourcePattern.at( patternIndex );
969 if ( currentRemainingGapLength == 0.0 )
977 buffer << remainingSegmentDistance << 0.0;
978 totalBufferLength += remainingSegmentDistance;
979 currentRemainingDashLength -= remainingSegmentDistance;
983 if ( currentRemainingGapLength > 0 )
986 if ( remainingSegmentDistance >= currentRemainingGapLength )
989 buffer << 0.0 << currentRemainingGapLength;
990 totalBufferLength += currentRemainingGapLength;
991 remainingSegmentDistance -= currentRemainingGapLength;
992 currentRemainingGapLength = 0.0;
998 buffer << 0.0 << remainingSegmentDistance;
999 totalBufferLength += remainingSegmentDistance;
1000 currentRemainingGapLength -= remainingSegmentDistance;
1005 if ( patternIndex + 1 >= sourcePattern.size() )
1010 const double nextPatternDashLength = sourcePattern.at( patternIndex );
1011 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
1012 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1014 buffer << nextPatternDashLength << nextPatternGapLength;
1015 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1016 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1019 else if ( nextPatternDashLength <= remainingSegmentDistance )
1022 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1023 totalBufferLength += remainingSegmentDistance;
1024 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1025 currentRemainingDashLength = 0;
1032 buffer << remainingSegmentDistance << 0.0;
1033 totalBufferLength += remainingSegmentDistance;
1034 currentRemainingGapLength = 0;
1035 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1040 bufferedPoints << p1;
1041 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1043 QPointF nextPoint = *( ptIt + 1 );
1049 flushBuffer( &nextPoint );
1050 bufferedPoints << p1;
1053 if ( patternIndex % 2 == 1 )
1057 currentRemainingDashLength = sourcePattern.at( patternIndex );
1064 flushBuffer(
nullptr );
1065 if ( !previousSegmentBuffer.empty() )
1067 QPen adjustedPen = pen;
1068 adjustedPen.setStyle( Qt::SolidLine );
1069 painter->setPen( adjustedPen );
1071 path.addPolygon( previousSegmentBuffer );
1072 painter->drawPath( path );
1073 previousSegmentBuffer.clear();
1079 if ( mDrawInsidePolygon )
1093 unit = mCustomDashPatternUnit;
1094 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1131 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1136 return mAlignDashPattern;
1146 return mPatternCartographicTweakOnSharpCorners;
1151 mPatternCartographicTweakOnSharpCorners =
enabled;
1179 MyLine( QPointF p1, QPointF p2 )
1180 : mVertical( false )
1181 , mIncreasing( false )
1193 mIncreasing = ( p2.y() > p1.y() );
1198 mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
1199 mIncreasing = ( p2.x() > p1.x() );
1203 double x = ( p2.x() - p1.x() );
1204 double y = ( p2.y() - p1.y() );
1205 mLength = std::sqrt( x * x + y * y );
1211 double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
1219 QPointF diffForInterval(
double interval )
1222 return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
1224 double alpha = std::atan( mT );
1225 double dx = std::cos( alpha ) * interval;
1226 double dy = std::sin( alpha ) * interval;
1227 return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
1230 double length()
const {
return mLength; }
1245 : mRotateSymbols( rotateSymbol )
1246 , mInterval( interval )
1285 if ( mRenderingFeature )
1289 mFeatureSymbolOpacity = context.
opacity();
1290 mCurrentFeatureIsSelected = useSelectedColor;
1308 QString placementString = exprVal.toString();
1309 if ( placementString.compare( QLatin1String(
"interval" ), Qt::CaseInsensitive ) == 0 )
1313 else if ( placementString.compare( QLatin1String(
"vertex" ), Qt::CaseInsensitive ) == 0 )
1317 else if ( placementString.compare( QLatin1String(
"innervertices" ), Qt::CaseInsensitive ) == 0 )
1321 else if ( placementString.compare( QLatin1String(
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
1325 else if ( placementString.compare( QLatin1String(
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
1329 else if ( placementString.compare( QLatin1String(
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
1333 else if ( placementString.compare( QLatin1String(
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
1337 else if ( placementString.compare( QLatin1String(
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
1350 double averageOver = mAverageAngleLength;
1361 renderPolylineInterval( points, context, averageOver );
1363 renderPolylineCentral( points, context, averageOver );
1367 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1370 mHasRenderedFirstPart = mRenderingFeature;
1386 for (
int part = 0; part < mline.count(); ++part )
1388 const QPolygonF &points2 = mline[ part ];
1391 renderPolylineInterval( points2, context, averageOver );
1393 renderPolylineCentral( points2, context, averageOver );
1401 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1404 mHasRenderedFirstPart = mRenderingFeature;
1424 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1454 for (
int i = 0; i < rings->size(); ++i )
1487 mIntervalUnit = unit;
1488 mOffsetAlongLineUnit = unit;
1489 mAverageAngleLengthUnit = unit;
1514 map[QStringLiteral(
"rotate" )] = (
rotateSymbols() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1515 map[QStringLiteral(
"interval" )] = QString::number(
interval() );
1516 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
1517 map[QStringLiteral(
"offset_along_line" )] = QString::number(
offsetAlongLine() );
1524 map[QStringLiteral(
"average_angle_length" )] = QString::number( mAverageAngleLength );
1530 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
1531 map[QStringLiteral(
"place_on_every_part" )] = mPlaceOnEveryPart;
1537 return mPlaceOnEveryPart
1547 mRenderingFeature =
true;
1548 mHasRenderedFirstPart =
false;
1553 mRenderingFeature =
false;
1564 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1565 mFeatureSymbolOpacity = 1;
1594 if (
properties.contains( QStringLiteral(
"offset" ) ) )
1598 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
1602 if (
properties.contains( QStringLiteral(
"interval_unit" ) ) )
1606 if (
properties.contains( QStringLiteral(
"offset_along_line" ) ) )
1610 if (
properties.contains( QStringLiteral(
"offset_along_line_unit" ) ) )
1614 if (
properties.contains( ( QStringLiteral(
"offset_along_line_map_unit_scale" ) ) ) )
1619 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1623 if (
properties.contains( QStringLiteral(
"interval_map_unit_scale" ) ) )
1628 if (
properties.contains( QStringLiteral(
"average_angle_length" ) ) )
1632 if (
properties.contains( QStringLiteral(
"average_angle_unit" ) ) )
1636 if (
properties.contains( ( QStringLiteral(
"average_angle_map_unit_scale" ) ) ) )
1641 if (
properties.contains( QStringLiteral(
"placement" ) ) )
1643 if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"vertex" ) )
1645 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"lastvertex" ) )
1647 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"firstvertex" ) )
1649 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"centralpoint" ) )
1651 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"curvepoint" ) )
1653 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"segmentcenter" ) )
1658 else if (
properties.contains( QStringLiteral(
"placements" ) ) )
1664 if (
properties.contains( QStringLiteral(
"ring_filter" ) ) )
1674void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver )
1676 if ( points.isEmpty() )
1680 double lengthLeft = 0;
1712 if ( painterUnitInterval < 0 )
1715 double painterUnitOffsetAlongLine = 0;
1718 double totalLength = -1;
1739 if ( points.isClosed() )
1741 if ( painterUnitOffsetAlongLine > 0 )
1743 if ( totalLength < 0 )
1745 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1747 else if ( painterUnitOffsetAlongLine < 0 )
1749 if ( totalLength < 0 )
1751 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1763 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1765 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1767 QVector< QPointF > angleStartPoints;
1768 QVector< QPointF > symbolPoints;
1769 QVector< QPointF > angleEndPoints;
1777 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
1779 if ( symbolPoints.empty() )
1785 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1788 symbolPoints.pop_back();
1791 angleEndPoints.reserve( symbolPoints.size() );
1792 angleStartPoints.reserve( symbolPoints.size() );
1793 if ( averageOver <= painterUnitOffsetAlongLine )
1795 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
1799 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1801 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
1804 for (
int i = 0; i < symbolPoints.size(); ++ i )
1809 const QPointF pt = symbolPoints[i];
1810 const QPointF startPt = angleStartPoints[i];
1811 const QPointF endPt = angleEndPoints[i];
1813 MyLine l( startPt, endPt );
1828 QPointF lastPt = points[0];
1829 for (
int i = 1; i < points.count(); ++i )
1834 const QPointF &pt = points[i];
1840 MyLine l( lastPt, pt );
1841 QPointF diff = l.diffForInterval( painterUnitInterval );
1845 double c = 1 - lengthLeft / painterUnitInterval;
1847 lengthLeft += l.length();
1856 while ( lengthLeft > painterUnitInterval )
1860 lengthLeft -= painterUnitInterval;
1872static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1875 double a1 = MyLine( prevPt, pt ).angle();
1876 double a2 = MyLine( pt, nextPt ).angle();
1877 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1879 return std::atan2( unitY, unitX );
1884 if ( points.isEmpty() )
1889 int i = -1, maxCount = 0;
1890 bool isRing =
false;
1904 double totalLength = -1;
1924 if ( points.isClosed() )
1928 if ( totalLength < 0 )
1934 if ( totalLength < 0 )
2008 i = points.count() - 1;
2010 maxCount = points.count();
2018 maxCount = points.count() - 1;
2026 maxCount = points.count();
2027 if ( points.first() == points.last() )
2044 renderOffsetVertexAlongLine( points, i, distance, context,
placement );
2051 prevPoint = points.at( 0 );
2053 QPointF symbolPoint;
2054 for ( ; i < maxCount; ++i )
2065 QPointF currentPoint = points.at( i );
2066 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2067 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2070 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2071 currentPoint.x() - prevPoint.x() );
2074 prevPoint = currentPoint;
2078 symbolPoint = points.at( i );
2082 double angle = markerAngle( points, isRing, i );
2087 mFinalVertex = symbolPoint;
2093double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2096 const QPointF &pt = points[vertex];
2098 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2100 int prevIndex = vertex - 1;
2101 int nextIndex = vertex + 1;
2103 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2105 prevIndex = points.count() - 2;
2109 QPointF prevPoint, nextPoint;
2110 while ( prevIndex >= 0 )
2112 prevPoint = points[ prevIndex ];
2113 if ( prevPoint != pt )
2120 while ( nextIndex < points.count() )
2122 nextPoint = points[ nextIndex ];
2123 if ( nextPoint != pt )
2130 if ( prevIndex >= 0 && nextIndex < points.count() )
2132 angle = _averageAngle( prevPoint, pt, nextPoint );
2139 while ( vertex < points.size() - 1 )
2141 const QPointF &nextPt = points[vertex + 1];
2144 angle = MyLine( pt, nextPt ).angle();
2153 while ( vertex >= 1 )
2155 const QPointF &prevPt = points[vertex - 1];
2158 angle = MyLine( prevPt, pt ).angle();
2170 if ( points.isEmpty() )
2180 bool isRing =
false;
2181 if ( points.first() == points.last() )
2183 double angle = markerAngle( points, isRing, vertex );
2186 mFinalVertex = points[vertex];
2192 int pointIncrement = distance > 0 ? 1 : -1;
2193 QPointF previousPoint = points[vertex];
2194 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2195 int endPoint = distance > 0 ? points.count() - 1 : 0;
2196 double distanceLeft = std::fabs( distance );
2198 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2200 const QPointF &pt = points[i];
2202 if ( previousPoint == pt )
2206 MyLine l( previousPoint, pt );
2208 if ( distanceLeft < l.length() )
2211 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2217 mFinalVertex = markerPoint;
2223 distanceLeft -= l.length();
2230void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
double initialLag,
int numberPointsRequired )
2235 QVector< QPointF > points = p;
2236 const bool closedRing = points.first() == points.last();
2238 double lengthLeft = initialOffset;
2240 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2241 if ( initialLagLeft < 0 && closedRing )
2244 QPointF lastPt = points.constLast();
2245 QVector< QPointF > pseudoPoints;
2246 for (
int i = points.count() - 2; i > 0; --i )
2248 if ( initialLagLeft >= 0 )
2253 const QPointF &pt = points[i];
2258 MyLine l( lastPt, pt );
2259 initialLagLeft += l.length();
2264 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2266 points = pseudoPoints;
2271 while ( initialLagLeft < 0 )
2273 dest << points.constFirst();
2274 initialLagLeft += intervalPainterUnits;
2277 if ( initialLag > 0 )
2279 lengthLeft += intervalPainterUnits - initialLagLeft;
2282 QPointF lastPt = points[0];
2283 for (
int i = 1; i < points.count(); ++i )
2285 const QPointF &pt = points[i];
2289 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2298 MyLine l( lastPt, pt );
2299 QPointF diff = l.diffForInterval( intervalPainterUnits );
2303 double c = 1 - lengthLeft / intervalPainterUnits;
2305 lengthLeft += l.length();
2308 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2312 lengthLeft -= intervalPainterUnits;
2315 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2320 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2324 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2331 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2334 while ( dest.size() < numberPointsRequired )
2335 dest << points.constLast();
2339void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver )
2341 if ( !points.isEmpty() )
2345 QPolygonF::const_iterator it = points.constBegin();
2347 for ( ++it; it != points.constEnd(); ++it )
2349 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2350 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2356 const double midPoint = length / 2;
2359 double thisSymbolAngle = 0;
2361 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2363 QVector< QPointF > angleStartPoints;
2364 QVector< QPointF > symbolPoints;
2365 QVector< QPointF > angleEndPoints;
2367 collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
2368 collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
2369 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
2371 pt = symbolPoints.at( 1 );
2372 MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2373 thisSymbolAngle = l.angle();
2378 it = points.constBegin();
2380 qreal last_at = 0, next_at = 0;
2382 for ( ++it; it != points.constEnd(); ++it )
2385 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2386 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2387 if ( next_at >= midPoint )
2394 MyLine l( last, next );
2395 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2396 pt = last + ( next - last ) * k;
2397 thisSymbolAngle = l.angle();
2449 if ( props.contains( QStringLiteral(
"interval" ) ) )
2450 interval = props[QStringLiteral(
"interval" )].toDouble();
2451 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2452 rotate = ( props[QStringLiteral(
"rotate" )].toString() == QLatin1String(
"1" ) );
2454 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2461 return QStringLiteral(
"MarkerLine" );
2481 mMarker->setRenderHints( hints );
2494 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >(
rotateSymbols(),
interval() );
2501 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2503 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
2504 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2505 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2506 element.appendChild( symbolizerElem );
2536 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2537 symbolizerElem.appendChild( strokeElem );
2540 QDomElement graphicStrokeElem = doc.createElement( QStringLiteral(
"se:GraphicStroke" ) );
2541 strokeElem.appendChild( graphicStrokeElem );
2546 markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
2550 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) ) );
2554 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"Missing marker line symbol layer. Skip it." ) ) );
2557 if ( !gap.isEmpty() )
2559 QDomElement gapElem = doc.createElement( QStringLiteral(
"se:Gap" ) );
2561 graphicStrokeElem.appendChild( gapElem );
2566 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
2569 symbolizerElem.appendChild( perpOffsetElem );
2578 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2579 if ( strokeElem.isNull() )
2582 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
2583 if ( graphicStrokeElem.isNull() )
2591 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2593 if ( it.key() == QLatin1String(
"placement" ) )
2595 if ( it.value() == QLatin1String(
"points" ) )
2597 else if ( it.value() == QLatin1String(
"firstPoint" ) )
2599 else if ( it.value() == QLatin1String(
"lastPoint" ) )
2601 else if ( it.value() == QLatin1String(
"centralPoint" ) )
2604 else if ( it.value() == QLatin1String(
"rotateMarker" ) )
2610 std::unique_ptr< QgsMarkerSymbol > marker;
2624 QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"Gap" ) );
2625 if ( !gapElem.isNull() )
2628 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
2634 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
2635 if ( !perpOffsetElem.isNull() )
2638 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2643 double scaleFactor = 1.0;
2644 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
2667 mMarker->setDataDefinedSize( property );
2674 const double prevOpacity =
mMarker->opacity();
2677 mMarker->setOpacity( prevOpacity );
2682 mMarker->setLineAngle( angle );
2700 mMarker->renderPoint( point, feature, context, layer, selected );
2712 return mMarker->size( context );
2718 mMarker->setOutputUnit( unit );
2735 attr.unite(
mMarker->usedAttributes( context ) );
2750 return (
mMarker->size( context ) / 2.0 ) +
2772 if ( props.contains( QStringLiteral(
"interval" ) ) )
2773 interval = props[QStringLiteral(
"interval" )].toDouble();
2774 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2775 rotate = ( props[QStringLiteral(
"rotate" )] == QLatin1String(
"1" ) );
2777 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2779 if ( props.contains( QStringLiteral(
"hash_angle" ) ) )
2781 x->setHashAngle( props[QStringLiteral(
"hash_angle" )].toDouble() );
2784 if ( props.contains( QStringLiteral(
"hash_length" ) ) )
2785 x->setHashLength( props[QStringLiteral(
"hash_length" )].toDouble() );
2787 if ( props.contains( QStringLiteral(
"hash_length_unit" ) ) )
2790 if ( props.contains( QStringLiteral(
"hash_length_map_unit_scale" ) ) )
2798 return QStringLiteral(
"HashLine" );
2807 mHashSymbol->setRenderHints( hints );
2820 map[ QStringLiteral(
"hash_angle" ) ] = QString::number( mHashAngle );
2822 map[QStringLiteral(
"hash_length" )] = QString::number( mHashLength );
2831 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >(
rotateSymbols(),
interval() );
2833 x->setHashAngle( mHashAngle );
2834 x->setHashLength( mHashLength );
2835 x->setHashLengthUnit( mHashLengthUnit );
2836 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2842 mHashSymbol->setColor(
color );
2848 return mHashSymbol ? mHashSymbol->color() :
mColor;
2853 return mHashSymbol.get();
2864 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2865 mColor = mHashSymbol->color();
2871 mHashLength =
width;
2886 return ( mHashSymbol->width( context ) / 2.0 )
2894 mHashSymbol->setOutputUnit( unit );
2901 attr.unite( mHashSymbol->usedAttributes( context ) );
2909 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
2918 mHashSymbol->setDataDefinedWidth( property );
2931 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
2936 mSymbolLineAngle = angle;
2941 return mSymbolAngle;
2946 mSymbolAngle = angle;
2951 double lineLength = mHashLength;
2957 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
2971 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
2976 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
2993 const double prevOpacity = mHashSymbol->opacity();
2994 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
2996 mHashSymbol->setOpacity( prevOpacity );
3015 QPolygonF offsetPoints;
3018 renderLine( points, context, patternThickness, patternLength, brush );
3027 renderLine( part, context, patternThickness, patternLength, brush );
3032void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3033 const double patternLength,
const QBrush &sourceBrush )
3039 QBrush brush = sourceBrush;
3044 QPolygonF inputPoints;
3045 inputPoints.reserve( points.size() );
3047 double minX = std::numeric_limits< double >::max();
3048 double minY = std::numeric_limits< double >::max();
3049 double maxX = std::numeric_limits< double >::lowest();
3050 double maxY = std::numeric_limits< double >::lowest();
3052 for (
const QPointF &pt : std::as_const( points ) )
3059 minX = std::min( minX, pt.x() );
3060 minY = std::min( minY, pt.y() );
3061 maxX = std::max( maxX, pt.x() );
3062 maxY = std::max( maxY, pt.y() );
3065 if ( inputPoints.size() < 2 )
3069 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3071 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3074 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3075 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3077 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3078 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3080 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3081 if ( temporaryImage.isNull() )
3090 temporaryImage.fill( Qt::transparent );
3113 QPainterPathStroker stroker;
3114 stroker.setWidth( lineThickness );
3115 stroker.setCapStyle( cap );
3116 stroker.setJoinStyle( join );
3119 path.addPolygon( inputPoints );
3120 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3123 QPainter imagePainter;
3124 imagePainter.begin( &temporaryImage );
3126 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3128 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3129 imagePainter.setPen( Qt::NoPen );
3131 QPointF segmentStartPoint = inputPoints.at( 0 );
3134 double progressThroughImage = 0;
3136 QgsPoint prevSegmentPolygonEndLeft;
3137 QgsPoint prevSegmentPolygonEndRight;
3143 for (
int i = 1; i < inputPoints.size(); ++i )
3148 const QPointF segmentEndPoint = inputPoints.at( i );
3150 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3153 QgsPoint thisSegmentPolygonEndLeft;
3154 QgsPoint thisSegmentPolygonEndRight;
3156 QgsPoint thisSegmentPolygonEndLeftForPainter;
3157 QgsPoint thisSegmentPolygonEndRightForPainter;
3165 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3167 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3168 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3172 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtilsBase::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3173 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3176 const QgsPoint lastSegmentStartPointLeft =
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3177 const QgsPoint lastSegmentEndPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3178 const QgsPoint lastSegmentStartPointRight =
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3179 const QgsPoint lastSegmentEndPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3185 bool isIntersection =
false;
3187 if ( !isIntersection )
3188 prevSegmentPolygonEndLeft = startPointLeft;
3189 isIntersection =
false;
3190 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3191 if ( !isIntersection )
3192 prevSegmentPolygonEndRight = startPointRight;
3194 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3195 startLinePolygonRight = prevSegmentPolygonEndRight;
3199 prevSegmentPolygonEndLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3200 if ( cap != Qt::PenCapStyle::FlatCap )
3201 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3202 prevSegmentPolygonEndRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3203 if ( cap != Qt::PenCapStyle::FlatCap )
3204 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3208 if ( i < inputPoints.size() - 1 )
3213 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3215 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3216 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3221 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3224 const QgsPoint nextSegmentStartPointLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3225 const QgsPoint nextSegmentEndPointLeft =
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3226 const QgsPoint nextSegmentStartPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3227 const QgsPoint nextSegmentEndPointRight =
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3233 bool isIntersection =
false;
3235 if ( !isIntersection )
3236 thisSegmentPolygonEndLeft = endPointLeft;
3237 isIntersection =
false;
3238 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3239 if ( !isIntersection )
3240 thisSegmentPolygonEndRight = endPointRight;
3242 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3243 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3251 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3252 thisSegmentPolygonEndRight = startLinePolygonRight;
3254 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3255 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3259 thisSegmentPolygonEndLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3260 if ( cap != Qt::PenCapStyle::FlatCap )
3261 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3262 thisSegmentPolygonEndRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3263 if ( cap != Qt::PenCapStyle::FlatCap )
3264 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3266 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3267 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3273 QTransform brushTransform;
3274 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3275 brushTransform.rotate( -segmentAngleDegrees );
3276 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3280 brushTransform.translate( -( lineThickness / 2 ), 0 );
3282 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3284 brush.setTransform( brushTransform );
3285 imagePainter.setBrush( brush );
3288 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3289 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3290 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3291 << prevSegmentPolygonEndRight.
toQPointF()
3292 << prevSegmentPolygonEndLeft.
toQPointF() );
3295 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3296 imagePainter.setBrush( Qt::NoBrush );
3297 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3298 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3299 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3300 << prevSegmentPolygonEndRight.
toQPointF()
3301 << prevSegmentPolygonEndLeft.
toQPointF() );
3302 imagePainter.setPen( Qt::NoPen );
3307 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3308 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3309 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3310 progressThroughImage = fmod( progressThroughImage, patternLength );
3313 segmentStartPoint = segmentEndPoint;
3314 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3315 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3323 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3324 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3341 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique<QgsRasterLineSymbolLayer>();
3343 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3345 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3347 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3351 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3356 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
3357 res->setPath(
properties[QStringLiteral(
"imageFile" )].toString() );
3359 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3361 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3363 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3367 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3372 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3374 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3377 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
3379 res->setOpacity(
properties[QStringLiteral(
"alpha" )].toDouble() );
3382 return res.release();
3389 map[QStringLiteral(
"imageFile" )] =
mPath;
3391 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3398 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3402 map[QStringLiteral(
"alpha" )] = QString::number(
mOpacity );
3409 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3421 return res.release();
3426 const QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
3427 if ( it !=
properties.end() && it.value().userType() == QMetaType::Type::QString )
3443 return QStringLiteral(
"RasterLine" );
3458 bool cached =
false;
3460 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3461 static_cast< int >( std::ceil( scaledHeight ) ) ),
3486 double strokeWidth =
mWidth;
3503 bool cached =
false;
3505 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3506 static_cast< int >( std::ceil( scaledHeight ) ) ),
3511 if ( useSelectedColor )
3516 const QBrush brush( sourceImage );
3586 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique<QgsLineburstSymbolLayer>();
3588 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3590 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3592 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3596 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3601 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3603 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3605 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3609 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3614 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3616 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3619 if (
properties.contains( QStringLiteral(
"color_type" ) ) )
3622 if (
properties.contains( QStringLiteral(
"color" ) ) )
3626 if (
properties.contains( QStringLiteral(
"gradient_color2" ) ) )
3641 return res.release();
3648 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3655 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3661 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
3672 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique< QgsLineburstSymbolLayer >();
3688 return res.release();
3693 return QStringLiteral(
"Lineburst" );
3714 double strokeWidth =
mWidth;
3730 if ( useSelectedColor )
3734 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3745 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3757 gradient.setColorAt( 0.0, color1 );
3758 gradient.setColorAt( 1.0,
color2 );
3760 const QBrush brush( gradient );
3839 if ( props.contains( QStringLiteral(
"line_width" ) ) )
3841 width = props[QStringLiteral(
"line_width" )].toDouble();
3843 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
3845 width = props[QStringLiteral(
"outline_width" )].toDouble();
3847 else if ( props.contains( QStringLiteral(
"width" ) ) )
3849 width = props[QStringLiteral(
"width" )].toDouble();
3854 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
3858 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
3862 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
3867 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3869 if ( props.contains( QStringLiteral(
"offset" ) ) )
3870 l->setOffset( props[QStringLiteral(
"offset" )].toDouble() );
3871 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
3873 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3875 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
3877 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
3880 l->restoreOldDataDefinedProperties( props );
3887 return QStringLiteral(
"FilledLine" );
3922 Qt::PenJoinStyle join = mPenJoinStyle;
3931 Qt::PenCapStyle cap = mPenCapStyle;
3947 const double prevOpacity = mFill->opacity();
3948 mFill->setOpacity( mFill->opacity() * context.
opacity() );
3956 QPainterPathStroker stroker;
3957 stroker.setWidth( scaledWidth );
3958 stroker.setCapStyle( cap );
3959 stroker.setJoinStyle( join );
3965 path.addPolygon( points );
3966 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3967 const QPolygonF polygon = stroke.toFillPolygon();
3968 if ( !polygon.isEmpty() )
3970 mFill->renderPolygon( polygon,
nullptr, context.
feature(), context.
renderContext(), -1, useSelectedColor );
3984 for (
const QPolygonF &part : mline )
3987 path.addPolygon( part );
3988 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3989 const QPolygonF polygon = stroke.toFillPolygon();
3990 if ( !polygon.isEmpty() )
3992 mFill->renderPolygon( polygon,
nullptr, context.
feature(), context.
renderContext(), -1, useSelectedColor );
3999 mFill->setOpacity( prevOpacity );
4006 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
4011 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
4026 res->setSubSymbol( mFill->clone() );
4027 return res.release();
4062 attr.unite( mFill->usedAttributes( context ) );
4070 if ( mFill && mFill->hasDataDefinedProperties() )
4079 mFill->setColor(
c );
4084 return mFill ? mFill->color() :
mColor;
4091 || ( mFill && mFill->usesMapUnits() );
4098 mFill->setMapUnitScale( scale );
4105 return mFill->mapUnitScale();
4114 mFill->setOutputUnit( unit );
4121 return mFill->outputUnit();
MarkerLinePlacement
Defines how/where the symbols should be placed on a line.
@ CurvePoint
Place symbols at every virtual curve point in the line (used when rendering curved geometry types onl...
@ InnerVertices
Inner vertices (i.e. all vertices except the first and last vertex)
@ LastVertex
Place symbols on the last vertex in the line.
@ CentralPoint
Place symbols at the mid point of the line.
@ SegmentCenter
Place symbols at the center of every line segment.
@ Vertex
Place symbols on every vertex in the line.
@ Interval
Place symbols at regular intervals.
@ FirstVertex
Place symbols on the first vertex in the line.
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
@ IsSymbolLayerSubSymbol
Symbol is being rendered as a sub-symbol of a QgsSymbolLayer.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
GradientColorSource
Gradient color sources.
@ ColorRamp
Gradient color ramp.
@ CanCalculateMaskGeometryPerFeature
If present, indicates that mask geometry can safely be calculated per feature for the symbol layer....
@ Curve
An intermediate point on a segment defining the curvature of the segment.
@ Segment
The actual start or end point of a segment.
QFlags< SymbolLayerFlag > SymbolLayerFlags
Symbol layer flags.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes)
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
@ RenderingSubSymbol
Set whenever a sub-symbol of a parent symbol is currently being rendered. Can be used during symbol a...
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
QFlags< MarkerLinePlacement > MarkerLinePlacements
Base class for line symbol layer types which draws line sections using a QBrush.
Qt::PenCapStyle mPenCapStyle
Qt::PenJoinStyle mPenJoinStyle
void renderPolylineUsingBrush(const QPolygonF &points, QgsSymbolRenderContext &context, const QBrush &brush, double patternThickness, double patternLength)
Renders a polyline of points using the specified brush.
static bool isGeneralizableByDeviceBoundingBox(const QgsRectangle &envelope, float mapToPixelTol=1.0f)
Returns whether the device-envelope can be replaced by its BBOX when is applied the specified toleran...
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
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.
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
Abstract base class for color ramps.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Curve polygon geometry type.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Exports QGIS layers to the DXF format.
static double mapUnitScaleFactor(double scale, Qgis::RenderUnit symbolUnits, Qgis::DistanceUnit mapUnits, double mapUnitsPerPixel=1.0)
Returns scale factor for conversion to map units.
Qgis::DistanceUnit mapUnits() const
Retrieve map units.
double symbologyScale() const
Returns the reference scale for output.
void clipValueToMapUnitScale(double &value, const QgsMapUnitScale &scale, double pixelToMMFactor) const
Clips value to scale minimum/maximum.
RAII class to pop scope from an expression context on destruction.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
static const QString EXPR_GEOMETRY_POINT_COUNT
Inbuilt variable name for point count variable.
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
static const QString EXPR_GEOMETRY_RING_NUM
Inbuilt variable name for geometry ring number variable.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isCanceled() const
Tells whether the operation has been canceled already.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
A line symbol layer type which fills a stroked line with a QgsFillSymbol.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString layerType() const override
Returns a string that represents this layer type.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFilledLineSymbolLayer, using the settings serialized in the properties map (correspo...
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
~QgsFilledLineSymbolLayer() override
QgsFilledLineSymbolLayer(double width=DEFAULT_SIMPLELINE_WIDTH, QgsFillSymbol *fillSymbol=nullptr)
Constructor for QgsFilledLineSymbolLayer.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setColor(const QColor &c) override
Sets the "representative" color for the symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
QgsFilledLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
QgsMapUnitScale mapUnitScale() const override
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static bool segmentIntersection(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
void addStopsToGradient(QGradient *gradient, double opacity=1) const
Copy color ramp stops to a QGradient.
Line symbol layer type which draws repeating line sections along a line feature.
double hashAngle() const
Returns the angle to use when drawing the hashed lines sections, in degrees clockwise.
QgsHashedLineSymbolLayer(bool rotateSymbol=true, double interval=3)
Constructor for QgsHashedLineSymbolLayer.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setWidth(double width) override
Sets the width of the line symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
double width() const override
Returns the estimated width for the line symbol layer.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsHashedLineSymbolLayer, using the settings serialized in the properties map (correspo...
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsHashedLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
~QgsHashedLineSymbolLayer() override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QColor color() const override
Returns the "representative" color of the symbol layer.
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString layerType() const override
Returns a string that represents this layer type.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setHashAngle(double angle)
Sets the angle to use when drawing the hashed lines sections, in degrees clockwise.
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
static void overlayColor(QImage &image, const QColor &color)
Overlays a color onto an image.
Abstract base class for line symbol layers.
Qgis::RenderUnit mOffsetUnit
RenderRingFilter
Options for filtering rings when the line symbol layer is being used to render a polygon's rings.
@ ExteriorRingOnly
Render the exterior ring only.
@ InteriorRingsOnly
Render the interior rings only.
@ AllRings
Render both exterior and interior rings.
QgsMapUnitScale mWidthMapUnitScale
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void setWidthMapUnitScale(const QgsMapUnitScale &scale)
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit mWidthUnit
void setOffset(double offset)
Sets the line's offset.
RenderRingFilter mRingFilter
void setOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the line's offset.
void setWidthUnit(Qgis::RenderUnit unit)
Sets the units for the line's width.
virtual double width() const
Returns the estimated width for the line symbol layer.
QgsMapUnitScale mOffsetMapUnitScale
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the line's offset.
QgsMapUnitScale mapUnitScale() const override
void setRingFilter(QgsLineSymbolLayer::RenderRingFilter filter)
Sets the line symbol layer's ring filter, which controls which rings are rendered when the line symbo...
void setMapUnitScale(const QgsMapUnitScale &scale) override
double offset() const
Returns the line's offset.
Qgis::RenderUnit offsetUnit() const
Returns the units for the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
Line symbol layer type which draws a gradient pattern perpendicularly along a line.
std::unique_ptr< QgsColorRamp > mGradientRamp
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp used for the gradient line.
QColor color2() const
Returns the color for endpoint of gradient, only used if the gradient color type is set to SimpleTwoC...
Qgis::GradientColorSource mGradientColorType
QString layerType() const override
Returns a string that represents this layer type.
~QgsLineburstSymbolLayer() override
QgsLineburstSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsMapUnitScale mapUnitScale() const override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsLineburstSymbolLayer, using the settings serialized in the properties map (correspon...
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QgsLineburstSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, const QColor &color2=Qt::white)
Constructor for QgsLineburstSymbolLayer, with the specified start and end gradient colors.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsColorRamp * colorRamp()
Returns the color ramp used for the gradient line.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
void transformInPlace(double &x, double &y) const
Transforms map coordinates to device coordinates.
Struct for storing maximum and minimum scales for measurements in map units.
Line symbol layer type which draws repeating marker symbols along a line feature.
Q_DECL_DEPRECATED bool rotateMarker() const
Shall the marker be rotated.
std::unique_ptr< QgsMarkerSymbol > mMarker
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsMarkerLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
double width() const override
Returns the estimated width for the line symbol layer.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsMarkerLineSymbolLayer, using the settings serialized in the properties map (correspo...
QgsMarkerLineSymbolLayer(bool rotateMarker=DEFAULT_MARKERLINE_ROTATE, double interval=DEFAULT_MARKERLINE_INTERVAL)
Constructor for QgsMarkerLineSymbolLayer.
void setWidth(double width) override
Sets the width of the line symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
~QgsMarkerLineSymbolLayer() override
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QString layerType() const override
Returns a string that represents this layer type.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsMarkerLineSymbolLayer from an SLD XML DOM element.
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
Abstract base class for marker symbol layers.
A marker symbol type, for rendering Point and MultiPoint geometries.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Resolves relative paths into absolute paths and vice versa.
A class to represent a 2D point.
QgsPointXY project(double distance, double bearing) const
Returns a new point which corresponds to this point projected by a specified distance in a specified ...
Point geometry type, with support for z-dimension and m-values.
QPointF toQPointF() const
Returns the point as a QPointF.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const final
Returns the calculated value of the property with the specified key from within the collection.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
A store for object properties.
Line symbol layer type which draws line sections using a raster image file.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QgsRasterLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
double opacity() const
Returns the line opacity.
QString path() const
Returns the raster image path.
void setPath(const QString &path)
Set the raster image path.
QString layerType() const override
Returns a string that represents this layer type.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
QgsRasterLineSymbolLayer(const QString &path=QString())
Constructor for QgsRasterLineSymbolLayer, with the specified raster image path.
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsRasterLineSymbolLayer, using the settings serialized in the properties map (correspo...
QColor color() const override
Returns the "representative" color of the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsMapUnitScale mapUnitScale() const override
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
virtual ~QgsRasterLineSymbolLayer()
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
QgsVectorSimplifyMethod & vectorSimplifyMethod()
Returns the simplification settings to use when rendering vector layers.
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.
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
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.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
const QgsAbstractGeometry * geometry() const
Returns pointer to the unsegmentized geometry.
Scoped object for saving and restoring a QPainter object's state.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void setDrawInsidePolygon(bool drawInsidePolygon)
Sets whether the line should only be drawn inside polygons, and any portion of the line which falls o...
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QgsMapUnitScale mapUnitScale() const override
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QVector< qreal > customDashVector() const
Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the outline of polygon, using the given render context.
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
void setCustomDashPatternMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for lengths used in the custom dash pattern.
void setTrimDistanceEndMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the end of the line.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void setTrimDistanceEnd(double distance)
Sets the trim distance for the end of the line, which dictates a length from the end of the line at w...
double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets offset.
QgsSimpleLineSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, double width=DEFAULT_SIMPLELINE_WIDTH, Qt::PenStyle penStyle=DEFAULT_SIMPLELINE_PENSTYLE)
Constructor for QgsSimpleLineSymbolLayer.
~QgsSimpleLineSymbolLayer() override
void setUseCustomDashPattern(bool b)
Sets whether the line uses a custom dash pattern.
void setTweakDashPatternOnCorners(bool enabled)
Sets whether dash patterns tweaks should be applied on sharp corners, to ensure that a double-length ...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
void setCustomDashVector(const QVector< qreal > &vector)
Sets the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ren...
void setDashPatternOffset(double offset)
Sets the dash pattern offset, which dictates how far along the dash pattern the pattern should start ...
QColor dxfColor(QgsSymbolRenderContext &context) const override
Gets color.
QString layerType() const override
Returns a string that represents this layer type.
void setDashPatternOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the dash pattern offset.
QgsSimpleLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
void setAlignDashPattern(bool enabled)
Sets whether dash patterns should be aligned to the start and end of lines, by applying subtle tweaks...
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleLineSymbolLayer from an SLD XML DOM element.
double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets line width.
void setTrimDistanceStartMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the start of the line.
QVector< qreal > dxfCustomDashPattern(Qgis::RenderUnit &unit) const override
Gets dash pattern.
Qt::PenCapStyle penCapStyle() const
Returns the pen cap style used to render the line (e.g.
void setTrimDistanceEndUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the end of the line.
void setDashPatternOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the dash pattern offset.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setTrimDistanceStart(double distance)
Sets the trim distance for the start of the line, which dictates a length from the start of the line ...
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setTrimDistanceStartUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the start of the line.
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
void setCustomDashPatternUnit(Qgis::RenderUnit unit)
Sets the unit for lengths used in the custom dash pattern.
static QString encodePenStyle(Qt::PenStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static QString encodeColor(const QColor &color)
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static Qt::PenStyle decodePenStyle(const QString &str)
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static QString encodeRealVector(const QVector< qreal > &v)
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
bool shouldRenderUsingSelectionColor(const QgsSymbolRenderContext &context) const
Returns true if the symbol layer should be rendered using the selection color from the render context...
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
bool installMasks(QgsRenderContext &context, bool recursive, const QRectF &rect=QRectF())
When rendering, install masks on context painter.
void removeMasks(QgsRenderContext &context, bool recursive)
When rendering, remove previously installed masks from context painter if recursive is true masks are...
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
Property
Data definable properties.
@ SecondaryColor
Secondary color (eg for gradient fills)
@ File
Filename, eg for svg files.
@ DashPatternOffset
Dash pattern offset,.
@ OffsetAlongLine
Offset along line.
@ CustomDash
Custom dash pattern.
@ StrokeStyle
Stroke style (eg solid, dashed)
@ StrokeColor
Stroke color.
@ TrimStart
Trim distance from start of line.
@ CapStyle
Line cap style.
@ Placement
Line marker placement.
@ LineAngle
Line angle, or angle of hash lines for hash line symbols.
@ JoinStyle
Line join style.
@ AverageAngleLength
Length to average symbol angles over.
@ Interval
Line marker interval.
@ StrokeWidth
Stroke width.
@ LineDistance
Distance between lines, or length of lines for hash line symbols.
@ TrimEnd
Trim distance from end of line.
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
virtual Qgis::SymbolLayerFlags flags() const
Returns flags which control the symbol layer's behavior.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
const QgsFeature * feature() const
Returns the current feature being rendered.
Qgis::GeometryType originalGeometryType() const
Returns the geometry type for the original feature geometry being rendered.
QgsFields fields() const
Fields of the layer.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
qreal opacity() const
Returns the opacity for the symbol.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for all rendered symbols.
qreal opacity() const
Returns the opacity for the symbol.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
Base class for templated line symbols, e.g.
bool rotateSymbols() const
Returns true if the repeating symbols be rotated to match their line segment orientation.
Qgis::RenderUnit outputUnit() const FINAL
Returns the units to use for sizes and widths within the symbol layer.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
static void setCommonProperties(QgsTemplatedLineSymbolLayerBase *destLayer, const QVariantMap &properties)
Sets all common symbol properties in the destLayer, using the settings serialized in the properties m...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
QgsMapUnitScale mapUnitScale() const FINAL
void setMapUnitScale(const QgsMapUnitScale &scale) FINAL
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setIntervalUnit(Qgis::RenderUnit unit)
Sets the units for the interval between symbols.
void setAverageAngleUnit(Qgis::RenderUnit unit)
Sets the unit for the length over which the line's direction is averaged when calculating individual ...
double interval() const
Returns the interval between individual symbols.
void setOffsetAlongLineUnit(Qgis::RenderUnit unit)
Sets the unit used for calculating the offset along line for symbols.
void setAverageAngleMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the length over which the line's direction is averaged when calculating i...
const QgsMapUnitScale & intervalMapUnitScale() const
Returns the map unit scale for the interval between symbols.
double offsetAlongLine() const
Returns the offset along the line for the symbol placement.
~QgsTemplatedLineSymbolLayerBase() override
void copyTemplateSymbolProperties(QgsTemplatedLineSymbolLayerBase *destLayer) const
Copies all common properties of this layer to another templated symbol layer.
Qgis::MarkerLinePlacements placements() const
Returns the placement of the symbols.
void setOffsetAlongLine(double offsetAlongLine)
Sets the the offset along the line for the symbol placement.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) FINAL
Renders the line symbol layer along the outline of polygon, using the given render context.
Qgis::RenderUnit offsetAlongLineUnit() const
Returns the unit used for calculating the offset along line for symbols.
QgsTemplatedLineSymbolLayerBase(bool rotateSymbol=true, double interval=3)
Constructor for QgsTemplatedLineSymbolLayerBase.
virtual void setSymbolLineAngle(double angle)=0
Sets the line angle modification for the symbol's angle.
void setInterval(double interval)
Sets the interval between individual symbols.
Qgis::RenderUnit intervalUnit() const
Returns the units for the interval between symbols.
Q_DECL_DEPRECATED Qgis::MarkerLinePlacement placement() const
Returns the placement of the symbols.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void setPlaceOnEveryPart(bool respect)
Sets whether the placement applies for every part of multi-part feature geometries.
void setPlacements(Qgis::MarkerLinePlacements placements)
Sets the placement of the symbols.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit averageAngleUnit() const
Returns the unit for the length over which the line's direction is averaged when calculating individu...
Q_DECL_DEPRECATED void setPlacement(Qgis::MarkerLinePlacement placement)
Sets the placement of the symbols.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
const QgsMapUnitScale & offsetAlongLineMapUnitScale() const
Returns the map unit scale used for calculating the offset in map units along line for symbols.
virtual void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false)=0
Renders the templated symbol at the specified point, using the given render context.
void setIntervalMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the interval between symbols.
void setOffsetAlongLineMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale used for calculating the offset in map units along line for symbols.
void setAverageAngleLength(double length)
Sets the length of line over which the line's direction is averaged when calculating individual symbo...
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.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Qgis::VectorRenderingSimplificationFlags simplifyHints() const
Gets the simplification hints of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QMap< QString, QString > QgsStringMap
#define DEFAULT_MARKERLINE_INTERVAL
#define DEFAULT_SIMPLELINE_WIDTH
#define DEFAULT_MARKERLINE_ROTATE
#define DEFAULT_SIMPLELINE_PENSTYLE
#define DEFAULT_SIMPLELINE_COLOR
#define QgsDebugMsgLevel(str, level)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
Single variable definition for use within a QgsExpressionContextScope.
Utility class for identifying a unique vertex within a geometry.
Qgis::VertexType type
Vertex type.