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" );
238 mPen.setColor( penColor );
240 mPen.setWidthF( scaledWidth );
244 const double dashWidthDiv = std::max( 1.0, scaledWidth );
245 if ( mUseCustomDashPattern )
247 mPen.setStyle( Qt::CustomDashLine );
251 QVector<qreal> scaledVector;
252 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
253 for ( ; it != mCustomDashVector.constEnd(); ++it )
258 mPen.setDashPattern( scaledVector );
262 mPen.setStyle( mPenStyle );
265 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
270 mPen.setJoinStyle( mPenJoinStyle );
271 mPen.setCapStyle( mPenCapStyle );
276 selColor.setAlphaF( context.
opacity() );
277 mSelPen.setColor( selColor );
294 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
301 if ( mDrawInsidePolygon )
309 if ( mDrawInsidePolygon )
312 QPainterPath clipPath;
313 clipPath.addPolygon( points );
318 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
320 QPolygonF ring = *it;
321 clipPath.addPolygon( ring );
326 p->setClipPath( clipPath, Qt::IntersectClip );
349 for (
const QPolygonF &ring : std::as_const( *rings ) )
365 if ( mDrawInsidePolygon )
381 QPolygonF points = pts;
383 double startTrim = mTrimDistanceStart;
389 double endTrim = mTrimDistanceEnd;
396 double totalLength = -1;
400 startTrim = startTrim * 0.01 * totalLength;
408 if ( totalLength < 0 )
410 endTrim = endTrim * 0.01 * totalLength;
423 mPen.setColor( penColor );
426 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
429 const QPen pen = useSelectedColor ? mSelPen : mPen;
431 if ( !pen.dashPattern().isEmpty() )
434 const QVector<double> pattern = pen.dashPattern();
435 bool foundNonNull =
false;
436 for (
int i = 0; i < pattern.size(); ++i )
448 p->setBrush( Qt::NoBrush );
451 std::unique_ptr< QgsScopedQPainterState > painterState;
452 if ( points.size() <= 2 &&
455 ( p->renderHints() & QPainter::Antialiasing ) )
457 painterState = std::make_unique< QgsScopedQPainterState >( p );
458 p->setRenderHint( QPainter::Antialiasing,
false );
461 const bool applyPatternTweaks = mAlignDashPattern
462 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
463 && pen.dashOffset() == 0;
467 if ( applyPatternTweaks )
469 drawPathWithDashPatternTweaks( p, points, pen );
475 path.addPolygon( points );
490 for (
const QPolygonF &part : mline )
492 if ( applyPatternTweaks )
494 drawPathWithDashPatternTweaks( p, part, pen );
500 path.addPolygon( part );
511 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
517 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
520 map[QStringLiteral(
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
524 map[QStringLiteral(
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
527 map[QStringLiteral(
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
530 map[QStringLiteral(
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
533 map[QStringLiteral(
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
534 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
535 map[QStringLiteral(
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
536 map[QStringLiteral(
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
575 if ( mPenStyle == Qt::NoPen )
578 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
579 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
580 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
581 element.appendChild( symbolizerElem );
587 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
588 symbolizerElem.appendChild( strokeElem );
590 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
599 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
602 symbolizerElem.appendChild( perpOffsetElem );
608 if ( mUseCustomDashPattern )
611 mPen.color(), mPenJoinStyle,
612 mPenCapStyle,
mOffset, &mCustomDashVector );
625 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
626 if ( strokeElem.isNull() )
643 QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
644 if ( !perpOffsetElem.isNull() )
647 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
652 double scaleFactor = 1.0;
653 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
668void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
674 bool hasStrokeWidthExpression =
false;
681 pen.setWidthF( scaledWidth );
682 selPen.setWidthF( scaledWidth );
683 hasStrokeWidthExpression =
true;
692 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
693 pen.setColor( penColor );
707 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
711 QVector<qreal> dashVector;
715 QStringList dashList = exprVal.toString().split(
';' );
716 QStringList::const_iterator dashIt = dashList.constBegin();
717 for ( ; dashIt != dashList.constEnd(); ++dashIt )
721 pen.setDashPattern( dashVector );
728 QVector<qreal> scaledVector;
729 for (
double v : std::as_const( mCustomDashVector ) )
734 mPen.setDashPattern( scaledVector );
738 double patternOffset = mDashPatternOffset;
774void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
776 if ( pen.dashPattern().empty() || points.size() < 2 )
779 if ( pen.widthF() <= 1.0 )
781 pen.setWidthF( 1.0001 );
784 QVector< qreal > sourcePattern = pen.dashPattern();
785 const double dashWidthDiv = pen.widthF();
787 for (
int i = 0; i < sourcePattern.size(); ++ i )
788 sourcePattern[i] *= pen.widthF();
790 QVector< qreal > buffer;
791 QPolygonF bufferedPoints;
792 QPolygonF previousSegmentBuffer;
797 auto ptIt = points.constBegin();
798 double totalBufferLength = 0;
799 int patternIndex = 0;
800 double currentRemainingDashLength = 0;
801 double currentRemainingGapLength = 0;
803 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
805 QVector< qreal > result;
806 result.reserve( buffer.size() );
807 for (
auto it = buffer.begin(); it != buffer.end(); )
811 while ( dash == 0 && !result.empty() )
813 result.last() += gap;
815 if ( it == buffer.end() )
820 while ( gap == 0 && it != buffer.end() )
825 result << dash << gap;
830 double currentBufferLineLength = 0;
831 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
832 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
834 if ( buffer.empty() || bufferedPoints.size() < 2 )
839 if ( currentRemainingDashLength )
842 buffer << currentRemainingDashLength << 0.0;
843 totalBufferLength += currentRemainingDashLength;
845 QVector< qreal > compressed = compressPattern( buffer );
846 if ( !currentRemainingDashLength )
849 totalBufferLength -= compressed.last();
850 compressed.last() = 0;
854 const double scaleFactor = currentBufferLineLength / totalBufferLength;
856 bool shouldFlushPreviousSegmentBuffer =
false;
858 if ( !previousSegmentBuffer.empty() )
862 if ( !firstDashSubstring.empty() )
868 compressed = compressed.mid( 2 );
869 shouldFlushPreviousSegmentBuffer = !compressed.empty();
872 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
874 QPen adjustedPen = pen;
875 adjustedPen.setStyle( Qt::SolidLine );
876 painter->setPen( adjustedPen );
878 path.addPolygon( previousSegmentBuffer );
879 painter->drawPath( path );
880 previousSegmentBuffer.clear();
883 double finalDash = 0;
890 if ( !compressed.empty() )
892 finalDash = compressed.at( compressed.size() - 2 );
893 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
895 const QPolygonF thisPoints = bufferedPoints;
901 previousSegmentBuffer << bufferedPoints;
905 currentBufferLineLength = 0;
906 currentRemainingDashLength = 0;
907 currentRemainingGapLength = 0;
908 totalBufferLength = 0;
911 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
913 QPen adjustedPen = pen;
914 if ( !compressed.empty() )
917 compressed = compressed.mid( 0, 32 );
918 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
919 adjustedPen.setDashPattern( compressed );
923 adjustedPen.setStyle( Qt::SolidLine );
926 painter->setPen( adjustedPen );
928 path.addPolygon( bufferedPoints );
929 painter->drawPath( path );
932 bufferedPoints.clear();
938 bufferedPoints << p2;
939 for ( ; ptIt != points.constEnd(); ++ptIt )
947 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
948 currentBufferLineLength += remainingSegmentDistance;
952 if ( currentRemainingDashLength > 0 )
955 if ( remainingSegmentDistance >= currentRemainingDashLength )
958 buffer << currentRemainingDashLength << 0.0;
959 totalBufferLength += currentRemainingDashLength;
960 remainingSegmentDistance -= currentRemainingDashLength;
962 currentRemainingDashLength = 0.0;
963 currentRemainingGapLength = sourcePattern.at( patternIndex );
964 if ( currentRemainingGapLength == 0.0 )
972 buffer << remainingSegmentDistance << 0.0;
973 totalBufferLength += remainingSegmentDistance;
974 currentRemainingDashLength -= remainingSegmentDistance;
978 if ( currentRemainingGapLength > 0 )
981 if ( remainingSegmentDistance >= currentRemainingGapLength )
984 buffer << 0.0 << currentRemainingGapLength;
985 totalBufferLength += currentRemainingGapLength;
986 remainingSegmentDistance -= currentRemainingGapLength;
987 currentRemainingGapLength = 0.0;
993 buffer << 0.0 << remainingSegmentDistance;
994 totalBufferLength += remainingSegmentDistance;
995 currentRemainingGapLength -= remainingSegmentDistance;
1000 if ( patternIndex + 1 >= sourcePattern.size() )
1005 const double nextPatternDashLength = sourcePattern.at( patternIndex );
1006 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
1007 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1009 buffer << nextPatternDashLength << nextPatternGapLength;
1010 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1011 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1014 else if ( nextPatternDashLength <= remainingSegmentDistance )
1017 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1018 totalBufferLength += remainingSegmentDistance;
1019 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1020 currentRemainingDashLength = 0;
1027 buffer << remainingSegmentDistance << 0.0;
1028 totalBufferLength += remainingSegmentDistance;
1029 currentRemainingGapLength = 0;
1030 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1035 bufferedPoints << p1;
1036 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1038 QPointF nextPoint = *( ptIt + 1 );
1044 flushBuffer( &nextPoint );
1045 bufferedPoints << p1;
1048 if ( patternIndex % 2 == 1 )
1052 currentRemainingDashLength = sourcePattern.at( patternIndex );
1059 flushBuffer(
nullptr );
1060 if ( !previousSegmentBuffer.empty() )
1062 QPen adjustedPen = pen;
1063 adjustedPen.setStyle( Qt::SolidLine );
1064 painter->setPen( adjustedPen );
1066 path.addPolygon( previousSegmentBuffer );
1067 painter->drawPath( path );
1068 previousSegmentBuffer.clear();
1074 if ( mDrawInsidePolygon )
1088 unit = mCustomDashPatternUnit;
1089 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1126 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1131 return mAlignDashPattern;
1141 return mPatternCartographicTweakOnSharpCorners;
1146 mPatternCartographicTweakOnSharpCorners =
enabled;
1174 MyLine( QPointF p1, QPointF p2 )
1175 : mVertical( false )
1176 , mIncreasing( false )
1188 mIncreasing = ( p2.y() > p1.y() );
1193 mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
1194 mIncreasing = ( p2.x() > p1.x() );
1198 double x = ( p2.x() - p1.x() );
1199 double y = ( p2.y() - p1.y() );
1200 mLength = std::sqrt( x * x + y * y );
1206 double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
1214 QPointF diffForInterval(
double interval )
1217 return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
1219 double alpha = std::atan( mT );
1220 double dx = std::cos( alpha ) * interval;
1221 double dy = std::sin( alpha ) * interval;
1222 return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
1225 double length()
const {
return mLength; }
1240 : mRotateSymbols( rotateSymbol )
1241 , mInterval( interval )
1280 if ( mRenderingFeature )
1284 mFeatureSymbolOpacity = context.
opacity();
1285 mCurrentFeatureIsSelected = useSelectedColor;
1303 QString placementString = exprVal.toString();
1304 if ( placementString.compare( QLatin1String(
"interval" ), Qt::CaseInsensitive ) == 0 )
1308 else if ( placementString.compare( QLatin1String(
"vertex" ), Qt::CaseInsensitive ) == 0 )
1312 else if ( placementString.compare( QLatin1String(
"innervertices" ), Qt::CaseInsensitive ) == 0 )
1316 else if ( placementString.compare( QLatin1String(
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
1320 else if ( placementString.compare( QLatin1String(
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
1324 else if ( placementString.compare( QLatin1String(
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
1328 else if ( placementString.compare( QLatin1String(
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
1332 else if ( placementString.compare( QLatin1String(
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
1345 double averageOver = mAverageAngleLength;
1356 renderPolylineInterval( points, context, averageOver );
1358 renderPolylineCentral( points, context, averageOver );
1362 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1365 mHasRenderedFirstPart = mRenderingFeature;
1381 for (
int part = 0; part < mline.count(); ++part )
1383 const QPolygonF &points2 = mline[ part ];
1386 renderPolylineInterval( points2, context, averageOver );
1388 renderPolylineCentral( points2, context, averageOver );
1396 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1399 mHasRenderedFirstPart = mRenderingFeature;
1419 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1449 for (
int i = 0; i < rings->size(); ++i )
1482 mIntervalUnit = unit;
1483 mOffsetAlongLineUnit = unit;
1484 mAverageAngleLengthUnit = unit;
1509 map[QStringLiteral(
"rotate" )] = (
rotateSymbols() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1510 map[QStringLiteral(
"interval" )] = QString::number(
interval() );
1511 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
1512 map[QStringLiteral(
"offset_along_line" )] = QString::number(
offsetAlongLine() );
1519 map[QStringLiteral(
"average_angle_length" )] = QString::number( mAverageAngleLength );
1525 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
1526 map[QStringLiteral(
"place_on_every_part" )] = mPlaceOnEveryPart;
1532 return mPlaceOnEveryPart
1542 mRenderingFeature =
true;
1543 mHasRenderedFirstPart =
false;
1548 mRenderingFeature =
false;
1559 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1560 mFeatureSymbolOpacity = 1;
1589 if (
properties.contains( QStringLiteral(
"offset" ) ) )
1593 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
1597 if (
properties.contains( QStringLiteral(
"interval_unit" ) ) )
1601 if (
properties.contains( QStringLiteral(
"offset_along_line" ) ) )
1605 if (
properties.contains( QStringLiteral(
"offset_along_line_unit" ) ) )
1609 if (
properties.contains( ( QStringLiteral(
"offset_along_line_map_unit_scale" ) ) ) )
1614 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1618 if (
properties.contains( QStringLiteral(
"interval_map_unit_scale" ) ) )
1623 if (
properties.contains( QStringLiteral(
"average_angle_length" ) ) )
1627 if (
properties.contains( QStringLiteral(
"average_angle_unit" ) ) )
1631 if (
properties.contains( ( QStringLiteral(
"average_angle_map_unit_scale" ) ) ) )
1636 if (
properties.contains( QStringLiteral(
"placement" ) ) )
1638 if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"vertex" ) )
1640 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"lastvertex" ) )
1642 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"firstvertex" ) )
1644 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"centralpoint" ) )
1646 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"curvepoint" ) )
1648 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"segmentcenter" ) )
1653 else if (
properties.contains( QStringLiteral(
"placements" ) ) )
1659 if (
properties.contains( QStringLiteral(
"ring_filter" ) ) )
1669void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver )
1671 if ( points.isEmpty() )
1675 double lengthLeft = 0;
1707 if ( painterUnitInterval < 0 )
1710 double painterUnitOffsetAlongLine = 0;
1713 double totalLength = -1;
1734 if ( points.isClosed() )
1736 if ( painterUnitOffsetAlongLine > 0 )
1738 if ( totalLength < 0 )
1740 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1742 else if ( painterUnitOffsetAlongLine < 0 )
1744 if ( totalLength < 0 )
1746 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1758 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1760 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1762 QVector< QPointF > angleStartPoints;
1763 QVector< QPointF > symbolPoints;
1764 QVector< QPointF > angleEndPoints;
1772 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
1774 if ( symbolPoints.empty() )
1780 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1783 symbolPoints.pop_back();
1786 angleEndPoints.reserve( symbolPoints.size() );
1787 angleStartPoints.reserve( symbolPoints.size() );
1788 if ( averageOver <= painterUnitOffsetAlongLine )
1790 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
1794 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1796 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
1799 for (
int i = 0; i < symbolPoints.size(); ++ i )
1804 const QPointF pt = symbolPoints[i];
1805 const QPointF startPt = angleStartPoints[i];
1806 const QPointF endPt = angleEndPoints[i];
1808 MyLine l( startPt, endPt );
1823 QPointF lastPt = points[0];
1824 for (
int i = 1; i < points.count(); ++i )
1829 const QPointF &pt = points[i];
1835 MyLine l( lastPt, pt );
1836 QPointF diff = l.diffForInterval( painterUnitInterval );
1840 double c = 1 - lengthLeft / painterUnitInterval;
1842 lengthLeft += l.length();
1851 while ( lengthLeft > painterUnitInterval )
1855 lengthLeft -= painterUnitInterval;
1867static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1870 double a1 = MyLine( prevPt, pt ).angle();
1871 double a2 = MyLine( pt, nextPt ).angle();
1872 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1874 return std::atan2( unitY, unitX );
1879 if ( points.isEmpty() )
1884 int i = -1, maxCount = 0;
1885 bool isRing =
false;
1899 double totalLength = -1;
1919 if ( points.isClosed() )
1923 if ( totalLength < 0 )
1929 if ( totalLength < 0 )
2003 i = points.count() - 1;
2005 maxCount = points.count();
2013 maxCount = points.count() - 1;
2021 maxCount = points.count();
2022 if ( points.first() == points.last() )
2039 renderOffsetVertexAlongLine( points, i, distance, context,
placement );
2046 prevPoint = points.at( 0 );
2048 QPointF symbolPoint;
2049 for ( ; i < maxCount; ++i )
2060 QPointF currentPoint = points.at( i );
2061 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2062 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2065 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2066 currentPoint.x() - prevPoint.x() );
2069 prevPoint = currentPoint;
2073 symbolPoint = points.at( i );
2077 double angle = markerAngle( points, isRing, i );
2082 mFinalVertex = symbolPoint;
2088double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2091 const QPointF &pt = points[vertex];
2093 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2095 int prevIndex = vertex - 1;
2096 int nextIndex = vertex + 1;
2098 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2100 prevIndex = points.count() - 2;
2104 QPointF prevPoint, nextPoint;
2105 while ( prevIndex >= 0 )
2107 prevPoint = points[ prevIndex ];
2108 if ( prevPoint != pt )
2115 while ( nextIndex < points.count() )
2117 nextPoint = points[ nextIndex ];
2118 if ( nextPoint != pt )
2125 if ( prevIndex >= 0 && nextIndex < points.count() )
2127 angle = _averageAngle( prevPoint, pt, nextPoint );
2134 while ( vertex < points.size() - 1 )
2136 const QPointF &nextPt = points[vertex + 1];
2139 angle = MyLine( pt, nextPt ).angle();
2148 while ( vertex >= 1 )
2150 const QPointF &prevPt = points[vertex - 1];
2153 angle = MyLine( prevPt, pt ).angle();
2165 if ( points.isEmpty() )
2175 bool isRing =
false;
2176 if ( points.first() == points.last() )
2178 double angle = markerAngle( points, isRing, vertex );
2181 mFinalVertex = points[vertex];
2187 int pointIncrement = distance > 0 ? 1 : -1;
2188 QPointF previousPoint = points[vertex];
2189 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2190 int endPoint = distance > 0 ? points.count() - 1 : 0;
2191 double distanceLeft = std::fabs( distance );
2193 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2195 const QPointF &pt = points[i];
2197 if ( previousPoint == pt )
2201 MyLine l( previousPoint, pt );
2203 if ( distanceLeft < l.length() )
2206 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2212 mFinalVertex = markerPoint;
2218 distanceLeft -= l.length();
2225void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
double initialLag,
int numberPointsRequired )
2230 QVector< QPointF > points = p;
2231 const bool closedRing = points.first() == points.last();
2233 double lengthLeft = initialOffset;
2235 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2236 if ( initialLagLeft < 0 && closedRing )
2239 QPointF lastPt = points.constLast();
2240 QVector< QPointF > pseudoPoints;
2241 for (
int i = points.count() - 2; i > 0; --i )
2243 if ( initialLagLeft >= 0 )
2248 const QPointF &pt = points[i];
2253 MyLine l( lastPt, pt );
2254 initialLagLeft += l.length();
2259 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2261 points = pseudoPoints;
2266 while ( initialLagLeft < 0 )
2268 dest << points.constFirst();
2269 initialLagLeft += intervalPainterUnits;
2272 if ( initialLag > 0 )
2274 lengthLeft += intervalPainterUnits - initialLagLeft;
2277 QPointF lastPt = points[0];
2278 for (
int i = 1; i < points.count(); ++i )
2280 const QPointF &pt = points[i];
2284 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2293 MyLine l( lastPt, pt );
2294 QPointF diff = l.diffForInterval( intervalPainterUnits );
2298 double c = 1 - lengthLeft / intervalPainterUnits;
2300 lengthLeft += l.length();
2303 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2307 lengthLeft -= intervalPainterUnits;
2310 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2315 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2319 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2326 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2329 while ( dest.size() < numberPointsRequired )
2330 dest << points.constLast();
2334void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver )
2336 if ( !points.isEmpty() )
2340 QPolygonF::const_iterator it = points.constBegin();
2342 for ( ++it; it != points.constEnd(); ++it )
2344 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2345 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2351 const double midPoint = length / 2;
2354 double thisSymbolAngle = 0;
2356 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2358 QVector< QPointF > angleStartPoints;
2359 QVector< QPointF > symbolPoints;
2360 QVector< QPointF > angleEndPoints;
2362 collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
2363 collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
2364 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
2366 pt = symbolPoints.at( 1 );
2367 MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2368 thisSymbolAngle = l.angle();
2373 it = points.constBegin();
2375 qreal last_at = 0, next_at = 0;
2377 for ( ++it; it != points.constEnd(); ++it )
2380 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2381 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2382 if ( next_at >= midPoint )
2389 MyLine l( last, next );
2390 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2391 pt = last + ( next - last ) * k;
2392 thisSymbolAngle = l.angle();
2444 if ( props.contains( QStringLiteral(
"interval" ) ) )
2445 interval = props[QStringLiteral(
"interval" )].toDouble();
2446 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2447 rotate = ( props[QStringLiteral(
"rotate" )].toString() == QLatin1String(
"1" ) );
2449 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2456 return QStringLiteral(
"MarkerLine" );
2476 mMarker->setRenderHints( hints );
2489 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >(
rotateSymbols(),
interval() );
2496 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2498 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
2499 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2500 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2501 element.appendChild( symbolizerElem );
2531 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2532 symbolizerElem.appendChild( strokeElem );
2535 QDomElement graphicStrokeElem = doc.createElement( QStringLiteral(
"se:GraphicStroke" ) );
2536 strokeElem.appendChild( graphicStrokeElem );
2541 markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
2545 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) ) );
2549 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"Missing marker line symbol layer. Skip it." ) ) );
2552 if ( !gap.isEmpty() )
2554 QDomElement gapElem = doc.createElement( QStringLiteral(
"se:Gap" ) );
2556 graphicStrokeElem.appendChild( gapElem );
2561 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
2564 symbolizerElem.appendChild( perpOffsetElem );
2573 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2574 if ( strokeElem.isNull() )
2577 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
2578 if ( graphicStrokeElem.isNull() )
2586 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2588 if ( it.key() == QLatin1String(
"placement" ) )
2590 if ( it.value() == QLatin1String(
"points" ) )
2592 else if ( it.value() == QLatin1String(
"firstPoint" ) )
2594 else if ( it.value() == QLatin1String(
"lastPoint" ) )
2596 else if ( it.value() == QLatin1String(
"centralPoint" ) )
2599 else if ( it.value() == QLatin1String(
"rotateMarker" ) )
2605 std::unique_ptr< QgsMarkerSymbol > marker;
2619 QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"Gap" ) );
2620 if ( !gapElem.isNull() )
2623 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
2629 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
2630 if ( !perpOffsetElem.isNull() )
2633 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2638 double scaleFactor = 1.0;
2639 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
2662 mMarker->setDataDefinedSize( property );
2669 const double prevOpacity =
mMarker->opacity();
2672 mMarker->setOpacity( prevOpacity );
2677 mMarker->setLineAngle( angle );
2695 mMarker->renderPoint( point, feature, context, layer, selected );
2707 return mMarker->size( context );
2713 mMarker->setOutputUnit( unit );
2730 attr.unite(
mMarker->usedAttributes( context ) );
2745 return (
mMarker->size( context ) / 2.0 ) +
2767 if ( props.contains( QStringLiteral(
"interval" ) ) )
2768 interval = props[QStringLiteral(
"interval" )].toDouble();
2769 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2770 rotate = ( props[QStringLiteral(
"rotate" )] == QLatin1String(
"1" ) );
2772 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2774 if ( props.contains( QStringLiteral(
"hash_angle" ) ) )
2776 x->setHashAngle( props[QStringLiteral(
"hash_angle" )].toDouble() );
2779 if ( props.contains( QStringLiteral(
"hash_length" ) ) )
2780 x->setHashLength( props[QStringLiteral(
"hash_length" )].toDouble() );
2782 if ( props.contains( QStringLiteral(
"hash_length_unit" ) ) )
2785 if ( props.contains( QStringLiteral(
"hash_length_map_unit_scale" ) ) )
2793 return QStringLiteral(
"HashLine" );
2802 mHashSymbol->setRenderHints( hints );
2815 map[ QStringLiteral(
"hash_angle" ) ] = QString::number( mHashAngle );
2817 map[QStringLiteral(
"hash_length" )] = QString::number( mHashLength );
2826 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >(
rotateSymbols(),
interval() );
2828 x->setHashAngle( mHashAngle );
2829 x->setHashLength( mHashLength );
2830 x->setHashLengthUnit( mHashLengthUnit );
2831 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2837 mHashSymbol->setColor(
color );
2843 return mHashSymbol ? mHashSymbol->color() :
mColor;
2848 return mHashSymbol.get();
2859 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2860 mColor = mHashSymbol->color();
2866 mHashLength =
width;
2881 return ( mHashSymbol->width( context ) / 2.0 )
2889 mHashSymbol->setOutputUnit( unit );
2896 attr.unite( mHashSymbol->usedAttributes( context ) );
2904 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
2913 mHashSymbol->setDataDefinedWidth( property );
2926 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
2931 mSymbolLineAngle = angle;
2936 return mSymbolAngle;
2941 mSymbolAngle = angle;
2946 double lineLength = mHashLength;
2952 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
2966 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
2971 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
2988 const double prevOpacity = mHashSymbol->opacity();
2989 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
2991 mHashSymbol->setOpacity( prevOpacity );
3010 QPolygonF offsetPoints;
3013 renderLine( points, context, patternThickness, patternLength, brush );
3022 renderLine( part, context, patternThickness, patternLength, brush );
3027void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3028 const double patternLength,
const QBrush &sourceBrush )
3034 QBrush brush = sourceBrush;
3039 QPolygonF inputPoints;
3040 inputPoints.reserve( points.size() );
3042 double minX = std::numeric_limits< double >::max();
3043 double minY = std::numeric_limits< double >::max();
3044 double maxX = std::numeric_limits< double >::lowest();
3045 double maxY = std::numeric_limits< double >::lowest();
3047 for (
const QPointF &pt : std::as_const( points ) )
3054 minX = std::min( minX, pt.x() );
3055 minY = std::min( minY, pt.y() );
3056 maxX = std::max( maxX, pt.x() );
3057 maxY = std::max( maxY, pt.y() );
3060 if ( inputPoints.size() < 2 )
3064 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3066 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3069 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3070 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3072 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3073 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3075 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3076 if ( temporaryImage.isNull() )
3085 temporaryImage.fill( Qt::transparent );
3108 QPainterPathStroker stroker;
3109 stroker.setWidth( lineThickness );
3110 stroker.setCapStyle( cap );
3111 stroker.setJoinStyle( join );
3114 path.addPolygon( inputPoints );
3115 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3118 QPainter imagePainter;
3119 imagePainter.begin( &temporaryImage );
3121 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3123 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3124 imagePainter.setPen( Qt::NoPen );
3126 QPointF segmentStartPoint = inputPoints.at( 0 );
3129 double progressThroughImage = 0;
3131 QgsPoint prevSegmentPolygonEndLeft;
3132 QgsPoint prevSegmentPolygonEndRight;
3138 for (
int i = 1; i < inputPoints.size(); ++i )
3143 const QPointF segmentEndPoint = inputPoints.at( i );
3145 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3148 QgsPoint thisSegmentPolygonEndLeft;
3149 QgsPoint thisSegmentPolygonEndRight;
3151 QgsPoint thisSegmentPolygonEndLeftForPainter;
3152 QgsPoint thisSegmentPolygonEndRightForPainter;
3160 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3162 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3163 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3167 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtilsBase::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3168 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3171 const QgsPoint lastSegmentStartPointLeft =
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3172 const QgsPoint lastSegmentEndPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3173 const QgsPoint lastSegmentStartPointRight =
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3174 const QgsPoint lastSegmentEndPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3180 bool isIntersection =
false;
3182 if ( !isIntersection )
3183 prevSegmentPolygonEndLeft = startPointLeft;
3184 isIntersection =
false;
3185 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3186 if ( !isIntersection )
3187 prevSegmentPolygonEndRight = startPointRight;
3189 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3190 startLinePolygonRight = prevSegmentPolygonEndRight;
3194 prevSegmentPolygonEndLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3195 if ( cap != Qt::PenCapStyle::FlatCap )
3196 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3197 prevSegmentPolygonEndRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3198 if ( cap != Qt::PenCapStyle::FlatCap )
3199 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3203 if ( i < inputPoints.size() - 1 )
3208 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3210 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3211 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3216 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3219 const QgsPoint nextSegmentStartPointLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3220 const QgsPoint nextSegmentEndPointLeft =
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3221 const QgsPoint nextSegmentStartPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3222 const QgsPoint nextSegmentEndPointRight =
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3228 bool isIntersection =
false;
3230 if ( !isIntersection )
3231 thisSegmentPolygonEndLeft = endPointLeft;
3232 isIntersection =
false;
3233 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3234 if ( !isIntersection )
3235 thisSegmentPolygonEndRight = endPointRight;
3237 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3238 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3246 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3247 thisSegmentPolygonEndRight = startLinePolygonRight;
3249 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3250 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3254 thisSegmentPolygonEndLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3255 if ( cap != Qt::PenCapStyle::FlatCap )
3256 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3257 thisSegmentPolygonEndRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3258 if ( cap != Qt::PenCapStyle::FlatCap )
3259 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3261 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3262 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3268 QTransform brushTransform;
3269 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3270 brushTransform.rotate( -segmentAngleDegrees );
3271 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3275 brushTransform.translate( -( lineThickness / 2 ), 0 );
3277 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3279 brush.setTransform( brushTransform );
3280 imagePainter.setBrush( brush );
3283 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3284 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3285 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3286 << prevSegmentPolygonEndRight.
toQPointF()
3287 << prevSegmentPolygonEndLeft.
toQPointF() );
3290 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3291 imagePainter.setBrush( Qt::NoBrush );
3292 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3293 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3294 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3295 << prevSegmentPolygonEndRight.
toQPointF()
3296 << prevSegmentPolygonEndLeft.
toQPointF() );
3297 imagePainter.setPen( Qt::NoPen );
3302 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3303 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3304 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3305 progressThroughImage = fmod( progressThroughImage, patternLength );
3308 segmentStartPoint = segmentEndPoint;
3309 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3310 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3318 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3319 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3336 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique<QgsRasterLineSymbolLayer>();
3338 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3340 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3342 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3346 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3351 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
3352 res->setPath(
properties[QStringLiteral(
"imageFile" )].toString() );
3354 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3356 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3358 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3362 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3367 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3369 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3372 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
3374 res->setOpacity(
properties[QStringLiteral(
"alpha" )].toDouble() );
3377 return res.release();
3384 map[QStringLiteral(
"imageFile" )] =
mPath;
3386 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3393 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3397 map[QStringLiteral(
"alpha" )] = QString::number(
mOpacity );
3404 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3416 return res.release();
3421 const QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
3422 if ( it !=
properties.end() && it.value().userType() == QMetaType::Type::QString )
3438 return QStringLiteral(
"RasterLine" );
3448 bool cached =
false;
3450 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3451 static_cast< int >( std::ceil( scaledHeight ) ) ),
3476 double strokeWidth =
mWidth;
3493 bool cached =
false;
3495 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3496 static_cast< int >( std::ceil( scaledHeight ) ) ),
3501 if ( useSelectedColor )
3506 const QBrush brush( sourceImage );
3576 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique<QgsLineburstSymbolLayer>();
3578 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3580 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3582 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3586 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3591 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3593 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3595 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3599 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3604 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3606 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3609 if (
properties.contains( QStringLiteral(
"color_type" ) ) )
3612 if (
properties.contains( QStringLiteral(
"color" ) ) )
3616 if (
properties.contains( QStringLiteral(
"gradient_color2" ) ) )
3631 return res.release();
3638 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3645 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3651 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
3662 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique< QgsLineburstSymbolLayer >();
3678 return res.release();
3683 return QStringLiteral(
"Lineburst" );
3699 double strokeWidth =
mWidth;
3715 if ( useSelectedColor )
3719 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3730 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3742 gradient.setColorAt( 0.0, color1 );
3743 gradient.setColorAt( 1.0,
color2 );
3745 const QBrush brush( gradient );
3824 if ( props.contains( QStringLiteral(
"line_width" ) ) )
3826 width = props[QStringLiteral(
"line_width" )].toDouble();
3828 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
3830 width = props[QStringLiteral(
"outline_width" )].toDouble();
3832 else if ( props.contains( QStringLiteral(
"width" ) ) )
3834 width = props[QStringLiteral(
"width" )].toDouble();
3839 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
3843 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
3847 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
3852 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3854 if ( props.contains( QStringLiteral(
"offset" ) ) )
3855 l->setOffset( props[QStringLiteral(
"offset" )].toDouble() );
3856 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
3858 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3860 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
3862 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
3865 l->restoreOldDataDefinedProperties( props );
3872 return QStringLiteral(
"FilledLine" );
3906 Qt::PenJoinStyle join = mPenJoinStyle;
3915 Qt::PenCapStyle cap = mPenCapStyle;
3931 const double prevOpacity = mFill->opacity();
3932 mFill->setOpacity( mFill->opacity() * context.
opacity() );
3940 QPainterPathStroker stroker;
3941 stroker.setWidth( scaledWidth );
3942 stroker.setCapStyle( cap );
3943 stroker.setJoinStyle( join );
3949 path.addPolygon( points );
3950 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3951 const QPolygonF polygon = stroke.toFillPolygon();
3952 if ( !polygon.isEmpty() )
3954 mFill->renderPolygon( polygon,
nullptr, context.
feature(), context.
renderContext(), -1, useSelectedColor );
3968 for (
const QPolygonF &part : mline )
3971 path.addPolygon( part );
3972 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3973 const QPolygonF polygon = stroke.toFillPolygon();
3974 if ( !polygon.isEmpty() )
3976 mFill->renderPolygon( polygon,
nullptr, context.
feature(), context.
renderContext(), -1, useSelectedColor );
3983 mFill->setOpacity( prevOpacity );
3990 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3995 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
4010 res->setSubSymbol( mFill->clone() );
4011 return res.release();
4046 attr.unite( mFill->usedAttributes( context ) );
4054 if ( mFill && mFill->hasDataDefinedProperties() )
4063 mFill->setColor(
c );
4068 return mFill ? mFill->color() :
mColor;
4075 || ( mFill && mFill->usesMapUnits() );
4082 mFill->setMapUnitScale( scale );
4089 return mFill->mapUnitScale();
4098 mFill->setOutputUnit( unit );
4105 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) (since QGIS 3....
@ 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.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
GradientColorSource
Gradient color sources.
@ ColorRamp
Gradient color ramp.
@ Curve
An intermediate point on a segment defining the curvature of the segment.
@ Segment
The actual start or end point of a segment.
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.
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...
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 device coordinates to map 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.
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.
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 QgsVectorSimplifyMethod & vectorSimplifyMethod() const
Returns the simplification settings to use when rendering vector layers.
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...
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.
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 (since QGIS 3.20)
@ 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 (since QGIS 3.20)
void installMasks(QgsRenderContext &context, bool recursive)
When rendering, install masks on context painter if recursive is true masks are installed recursively...
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.
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.