40#include <QDomDocument>
46 : mPenStyle( penStyle )
50 mCustomDashVector << 5 << 2;
60 mCustomDashPatternUnit = unit;
61 mDashPatternOffsetUnit = unit;
62 mTrimDistanceStartUnit = unit;
63 mTrimDistanceEndUnit = unit;
87 mCustomDashPatternMapUnitScale = scale;
107 if ( props.contains( QStringLiteral(
"line_color" ) ) )
111 else if ( props.contains( QStringLiteral(
"outline_color" ) ) )
115 else if ( props.contains( QStringLiteral(
"color" ) ) )
120 if ( props.contains( QStringLiteral(
"line_width" ) ) )
122 width = props[QStringLiteral(
"line_width" )].toDouble();
124 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
126 width = props[QStringLiteral(
"outline_width" )].toDouble();
128 else if ( props.contains( QStringLiteral(
"width" ) ) )
131 width = props[QStringLiteral(
"width" )].toDouble();
133 if ( props.contains( QStringLiteral(
"line_style" ) ) )
137 else if ( props.contains( QStringLiteral(
"outline_style" ) ) )
141 else if ( props.contains( QStringLiteral(
"penstyle" ) ) )
147 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
151 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
155 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
160 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
162 if ( props.contains( QStringLiteral(
"offset" ) ) )
163 l->
setOffset( props[QStringLiteral(
"offset" )].toDouble() );
164 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
166 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
168 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
170 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
173 if ( props.contains( QStringLiteral(
"use_custom_dash" ) ) )
177 if ( props.contains( QStringLiteral(
"customdash" ) ) )
181 if ( props.contains( QStringLiteral(
"customdash_unit" ) ) )
185 if ( props.contains( QStringLiteral(
"customdash_map_unit_scale" ) ) )
190 if ( props.contains( QStringLiteral(
"draw_inside_polygon" ) ) )
195 if ( props.contains( QStringLiteral(
"ring_filter" ) ) )
200 if ( props.contains( QStringLiteral(
"dash_pattern_offset" ) ) )
202 if ( props.contains( QStringLiteral(
"dash_pattern_offset_unit" ) ) )
204 if ( props.contains( QStringLiteral(
"dash_pattern_offset_map_unit_scale" ) ) )
207 if ( props.contains( QStringLiteral(
"trim_distance_start" ) ) )
209 if ( props.contains( QStringLiteral(
"trim_distance_start_unit" ) ) )
211 if ( props.contains( QStringLiteral(
"trim_distance_start_map_unit_scale" ) ) )
213 if ( props.contains( QStringLiteral(
"trim_distance_end" ) ) )
215 if ( props.contains( QStringLiteral(
"trim_distance_end_unit" ) ) )
217 if ( props.contains( QStringLiteral(
"trim_distance_end_map_unit_scale" ) ) )
220 if ( props.contains( QStringLiteral(
"align_dash_pattern" ) ) )
223 if ( props.contains( QStringLiteral(
"tweak_dash_pattern_on_corners" ) ) )
233 return QStringLiteral(
"SimpleLine" );
245 mPen.setColor( penColor );
247 mPen.setWidthF( scaledWidth );
251 const double dashWidthDiv = std::max( 1.0, scaledWidth );
252 if ( mUseCustomDashPattern )
254 mPen.setStyle( Qt::CustomDashLine );
258 QVector<qreal> scaledVector;
259 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
260 for ( ; it != mCustomDashVector.constEnd(); ++it )
265 mPen.setDashPattern( scaledVector );
269 mPen.setStyle( mPenStyle );
272 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
277 mPen.setJoinStyle( mPenJoinStyle );
278 mPen.setCapStyle( mPenCapStyle );
283 selColor.setAlphaF( context.
opacity() );
284 mSelPen.setColor( selColor );
301 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
308 if ( mDrawInsidePolygon )
316 if ( mDrawInsidePolygon )
319 QPainterPath clipPath;
320 clipPath.addPolygon( points );
325 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
327 QPolygonF ring = *it;
328 clipPath.addPolygon( ring );
333 p->setClipPath( clipPath, Qt::IntersectClip );
356 for (
const QPolygonF &ring : std::as_const( *rings ) )
372 if ( mDrawInsidePolygon )
388 QPolygonF points = pts;
390 double startTrim = mTrimDistanceStart;
396 double endTrim = mTrimDistanceEnd;
403 double totalLength = -1;
407 startTrim = startTrim * 0.01 * totalLength;
415 if ( totalLength < 0 )
417 endTrim = endTrim * 0.01 * totalLength;
430 mPen.setColor( penColor );
433 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
436 const QPen pen = useSelectedColor ? mSelPen : mPen;
438 if ( !pen.dashPattern().isEmpty() )
441 const QVector<double> pattern = pen.dashPattern();
442 bool foundNonNull =
false;
443 for (
int i = 0; i < pattern.size(); ++i )
455 p->setBrush( Qt::NoBrush );
458 std::unique_ptr< QgsScopedQPainterState > painterState;
459 if ( points.size() <= 2 &&
462 ( p->renderHints() & QPainter::Antialiasing ) )
464 painterState = std::make_unique< QgsScopedQPainterState >( p );
465 p->setRenderHint( QPainter::Antialiasing,
false );
468 const bool applyPatternTweaks = mAlignDashPattern
469 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
470 && pen.dashOffset() == 0;
474 if ( applyPatternTweaks )
476 drawPathWithDashPatternTweaks( p, points, pen );
482 path.addPolygon( points );
497 for (
const QPolygonF &part : mline )
499 if ( applyPatternTweaks )
501 drawPathWithDashPatternTweaks( p, part, pen );
507 path.addPolygon( part );
518 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
524 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
527 map[QStringLiteral(
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
531 map[QStringLiteral(
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
534 map[QStringLiteral(
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
537 map[QStringLiteral(
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
540 map[QStringLiteral(
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
541 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
542 map[QStringLiteral(
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
543 map[QStringLiteral(
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
584 toSld( doc, element, context );
589 if ( mPenStyle == Qt::NoPen )
593 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
594 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
595 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
596 element.appendChild( symbolizerElem );
602 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
603 symbolizerElem.appendChild( strokeElem );
605 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
614 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
617 symbolizerElem.appendChild( perpOffsetElem );
624 if ( mUseCustomDashPattern )
627 mPen.color(), mPenJoinStyle,
628 mPenCapStyle,
mOffset, &mCustomDashVector );
641 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
642 if ( strokeElem.isNull() )
659 QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
660 if ( !perpOffsetElem.isNull() )
663 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
668 double scaleFactor = 1.0;
669 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
684void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
690 bool hasStrokeWidthExpression =
false;
697 pen.setWidthF( scaledWidth );
698 selPen.setWidthF( scaledWidth );
699 hasStrokeWidthExpression =
true;
708 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
709 pen.setColor( penColor );
723 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
727 QVector<qreal> dashVector;
731 QStringList dashList = exprVal.toString().split(
';' );
732 QStringList::const_iterator dashIt = dashList.constBegin();
733 for ( ; dashIt != dashList.constEnd(); ++dashIt )
737 pen.setDashPattern( dashVector );
744 QVector<qreal> scaledVector;
745 for (
double v : std::as_const( mCustomDashVector ) )
750 mPen.setDashPattern( scaledVector );
754 double patternOffset = mDashPatternOffset;
790void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
792 if ( pen.dashPattern().empty() || points.size() < 2 )
795 if ( pen.widthF() <= 1.0 )
797 pen.setWidthF( 1.0001 );
800 QVector< qreal > sourcePattern = pen.dashPattern();
801 const double dashWidthDiv = pen.widthF();
803 for (
int i = 0; i < sourcePattern.size(); ++ i )
804 sourcePattern[i] *= pen.widthF();
806 QVector< qreal > buffer;
807 QPolygonF bufferedPoints;
808 QPolygonF previousSegmentBuffer;
813 auto ptIt = points.constBegin();
814 double totalBufferLength = 0;
815 int patternIndex = 0;
816 double currentRemainingDashLength = 0;
817 double currentRemainingGapLength = 0;
819 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
821 QVector< qreal > result;
822 result.reserve( buffer.size() );
823 for (
auto it = buffer.begin(); it != buffer.end(); )
827 while ( dash == 0 && !result.empty() )
829 result.last() += gap;
831 if ( it == buffer.end() )
836 while ( gap == 0 && it != buffer.end() )
841 result << dash << gap;
846 double currentBufferLineLength = 0;
847 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
848 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
850 if ( buffer.empty() || bufferedPoints.size() < 2 )
855 if ( currentRemainingDashLength )
858 buffer << currentRemainingDashLength << 0.0;
859 totalBufferLength += currentRemainingDashLength;
861 QVector< qreal > compressed = compressPattern( buffer );
862 if ( !currentRemainingDashLength )
865 totalBufferLength -= compressed.last();
866 compressed.last() = 0;
870 const double scaleFactor = currentBufferLineLength / totalBufferLength;
872 bool shouldFlushPreviousSegmentBuffer =
false;
874 if ( !previousSegmentBuffer.empty() )
878 if ( !firstDashSubstring.empty() )
884 compressed = compressed.mid( 2 );
885 shouldFlushPreviousSegmentBuffer = !compressed.empty();
888 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
890 QPen adjustedPen = pen;
891 adjustedPen.setStyle( Qt::SolidLine );
892 painter->setPen( adjustedPen );
894 path.addPolygon( previousSegmentBuffer );
895 painter->drawPath( path );
896 previousSegmentBuffer.clear();
899 double finalDash = 0;
906 if ( !compressed.empty() )
908 finalDash = compressed.at( compressed.size() - 2 );
909 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
911 const QPolygonF thisPoints = bufferedPoints;
917 previousSegmentBuffer << bufferedPoints;
921 currentBufferLineLength = 0;
922 currentRemainingDashLength = 0;
923 currentRemainingGapLength = 0;
924 totalBufferLength = 0;
927 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
929 QPen adjustedPen = pen;
930 if ( !compressed.empty() )
933 compressed = compressed.mid( 0, 32 );
934 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
935 adjustedPen.setDashPattern( compressed );
939 adjustedPen.setStyle( Qt::SolidLine );
942 painter->setPen( adjustedPen );
944 path.addPolygon( bufferedPoints );
945 painter->drawPath( path );
948 bufferedPoints.clear();
954 bufferedPoints << p2;
955 for ( ; ptIt != points.constEnd(); ++ptIt )
963 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
964 currentBufferLineLength += remainingSegmentDistance;
968 if ( currentRemainingDashLength > 0 )
971 if ( remainingSegmentDistance >= currentRemainingDashLength )
974 buffer << currentRemainingDashLength << 0.0;
975 totalBufferLength += currentRemainingDashLength;
976 remainingSegmentDistance -= currentRemainingDashLength;
978 currentRemainingDashLength = 0.0;
979 currentRemainingGapLength = sourcePattern.at( patternIndex );
980 if ( currentRemainingGapLength == 0.0 )
988 buffer << remainingSegmentDistance << 0.0;
989 totalBufferLength += remainingSegmentDistance;
990 currentRemainingDashLength -= remainingSegmentDistance;
994 if ( currentRemainingGapLength > 0 )
997 if ( remainingSegmentDistance >= currentRemainingGapLength )
1000 buffer << 0.0 << currentRemainingGapLength;
1001 totalBufferLength += currentRemainingGapLength;
1002 remainingSegmentDistance -= currentRemainingGapLength;
1003 currentRemainingGapLength = 0.0;
1009 buffer << 0.0 << remainingSegmentDistance;
1010 totalBufferLength += remainingSegmentDistance;
1011 currentRemainingGapLength -= remainingSegmentDistance;
1016 if ( patternIndex + 1 >= sourcePattern.size() )
1021 const double nextPatternDashLength = sourcePattern.at( patternIndex );
1022 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
1023 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1025 buffer << nextPatternDashLength << nextPatternGapLength;
1026 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1027 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1030 else if ( nextPatternDashLength <= remainingSegmentDistance )
1033 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1034 totalBufferLength += remainingSegmentDistance;
1035 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1036 currentRemainingDashLength = 0;
1043 buffer << remainingSegmentDistance << 0.0;
1044 totalBufferLength += remainingSegmentDistance;
1045 currentRemainingGapLength = 0;
1046 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1051 bufferedPoints << p1;
1052 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1054 QPointF nextPoint = *( ptIt + 1 );
1060 flushBuffer( &nextPoint );
1061 bufferedPoints << p1;
1064 if ( patternIndex % 2 == 1 )
1068 currentRemainingDashLength = sourcePattern.at( patternIndex );
1075 flushBuffer(
nullptr );
1076 if ( !previousSegmentBuffer.empty() )
1078 QPen adjustedPen = pen;
1079 adjustedPen.setStyle( Qt::SolidLine );
1080 painter->setPen( adjustedPen );
1082 path.addPolygon( previousSegmentBuffer );
1083 painter->drawPath( path );
1084 previousSegmentBuffer.clear();
1090 if ( mDrawInsidePolygon )
1104 unit = mCustomDashPatternUnit;
1105 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1142 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1147 return mAlignDashPattern;
1157 return mPatternCartographicTweakOnSharpCorners;
1162 mPatternCartographicTweakOnSharpCorners =
enabled;
1190 MyLine( QPointF p1, QPointF p2 )
1191 : mVertical( false )
1192 , mIncreasing( false )
1204 mIncreasing = ( p2.y() > p1.y() );
1209 mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
1210 mIncreasing = ( p2.x() > p1.x() );
1214 double x = ( p2.x() - p1.x() );
1215 double y = ( p2.y() - p1.y() );
1216 mLength = std::sqrt( x * x + y * y );
1222 double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
1230 QPointF diffForInterval(
double interval )
1233 return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
1235 double alpha = std::atan( mT );
1236 double dx = std::cos( alpha ) * interval;
1237 double dy = std::sin( alpha ) * interval;
1238 return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
1241 double length()
const {
return mLength; }
1256 : mRotateSymbols( rotateSymbol )
1257 , mInterval( interval )
1296 if ( mRenderingFeature )
1300 mFeatureSymbolOpacity = context.
opacity();
1301 mCurrentFeatureIsSelected = useSelectedColor;
1319 QString placementString = exprVal.toString();
1320 if ( placementString.compare( QLatin1String(
"interval" ), Qt::CaseInsensitive ) == 0 )
1324 else if ( placementString.compare( QLatin1String(
"vertex" ), Qt::CaseInsensitive ) == 0 )
1328 else if ( placementString.compare( QLatin1String(
"innervertices" ), Qt::CaseInsensitive ) == 0 )
1332 else if ( placementString.compare( QLatin1String(
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
1336 else if ( placementString.compare( QLatin1String(
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
1340 else if ( placementString.compare( QLatin1String(
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
1344 else if ( placementString.compare( QLatin1String(
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
1348 else if ( placementString.compare( QLatin1String(
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
1361 double averageOver = mAverageAngleLength;
1372 renderPolylineInterval( points, context, averageOver );
1374 renderPolylineCentral( points, context, averageOver );
1378 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1381 mHasRenderedFirstPart = mRenderingFeature;
1397 for (
int part = 0; part < mline.count(); ++part )
1399 const QPolygonF &points2 = mline[ part ];
1402 renderPolylineInterval( points2, context, averageOver );
1404 renderPolylineCentral( points2, context, averageOver );
1412 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1415 mHasRenderedFirstPart = mRenderingFeature;
1435 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1465 for (
int i = 0; i < rings->size(); ++i )
1498 mIntervalUnit = unit;
1499 mOffsetAlongLineUnit = unit;
1500 mAverageAngleLengthUnit = unit;
1525 map[QStringLiteral(
"rotate" )] = (
rotateSymbols() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1526 map[QStringLiteral(
"interval" )] = QString::number(
interval() );
1527 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
1528 map[QStringLiteral(
"offset_along_line" )] = QString::number(
offsetAlongLine() );
1535 map[QStringLiteral(
"average_angle_length" )] = QString::number( mAverageAngleLength );
1541 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
1542 map[QStringLiteral(
"place_on_every_part" )] = mPlaceOnEveryPart;
1548 return mPlaceOnEveryPart
1558 mRenderingFeature =
true;
1559 mHasRenderedFirstPart =
false;
1564 mRenderingFeature =
false;
1575 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1576 mFeatureSymbolOpacity = 1;
1605 if (
properties.contains( QStringLiteral(
"offset" ) ) )
1609 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
1613 if (
properties.contains( QStringLiteral(
"interval_unit" ) ) )
1617 if (
properties.contains( QStringLiteral(
"offset_along_line" ) ) )
1621 if (
properties.contains( QStringLiteral(
"offset_along_line_unit" ) ) )
1625 if (
properties.contains( ( QStringLiteral(
"offset_along_line_map_unit_scale" ) ) ) )
1630 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1634 if (
properties.contains( QStringLiteral(
"interval_map_unit_scale" ) ) )
1639 if (
properties.contains( QStringLiteral(
"average_angle_length" ) ) )
1643 if (
properties.contains( QStringLiteral(
"average_angle_unit" ) ) )
1647 if (
properties.contains( ( QStringLiteral(
"average_angle_map_unit_scale" ) ) ) )
1652 if (
properties.contains( QStringLiteral(
"placement" ) ) )
1654 if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"vertex" ) )
1656 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"lastvertex" ) )
1658 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"firstvertex" ) )
1660 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"centralpoint" ) )
1662 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"curvepoint" ) )
1664 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"segmentcenter" ) )
1669 else if (
properties.contains( QStringLiteral(
"placements" ) ) )
1675 if (
properties.contains( QStringLiteral(
"ring_filter" ) ) )
1685void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver )
1687 if ( points.isEmpty() )
1691 double lengthLeft = 0;
1723 if ( painterUnitInterval < 0 )
1726 double painterUnitOffsetAlongLine = 0;
1729 double totalLength = -1;
1750 if ( points.isClosed() )
1752 if ( painterUnitOffsetAlongLine > 0 )
1754 if ( totalLength < 0 )
1756 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1758 else if ( painterUnitOffsetAlongLine < 0 )
1760 if ( totalLength < 0 )
1762 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1774 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1776 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1778 QVector< QPointF > angleStartPoints;
1779 QVector< QPointF > symbolPoints;
1780 QVector< QPointF > angleEndPoints;
1788 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
1790 if ( symbolPoints.empty() )
1796 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1799 symbolPoints.pop_back();
1802 angleEndPoints.reserve( symbolPoints.size() );
1803 angleStartPoints.reserve( symbolPoints.size() );
1804 if ( averageOver <= painterUnitOffsetAlongLine )
1806 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
1810 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1812 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
1815 for (
int i = 0; i < symbolPoints.size(); ++ i )
1820 const QPointF pt = symbolPoints[i];
1821 const QPointF startPt = angleStartPoints[i];
1822 const QPointF endPt = angleEndPoints[i];
1824 MyLine l( startPt, endPt );
1839 QPointF lastPt = points[0];
1840 for (
int i = 1; i < points.count(); ++i )
1845 const QPointF &pt = points[i];
1851 MyLine l( lastPt, pt );
1852 QPointF diff = l.diffForInterval( painterUnitInterval );
1856 double c = 1 - lengthLeft / painterUnitInterval;
1858 lengthLeft += l.length();
1867 while ( lengthLeft > painterUnitInterval )
1871 lengthLeft -= painterUnitInterval;
1883static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1886 double a1 = MyLine( prevPt, pt ).angle();
1887 double a2 = MyLine( pt, nextPt ).angle();
1888 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1890 return std::atan2( unitY, unitX );
1895 if ( points.isEmpty() )
1900 int i = -1, maxCount = 0;
1901 bool isRing =
false;
1915 double totalLength = -1;
1935 if ( points.isClosed() )
1939 if ( totalLength < 0 )
1945 if ( totalLength < 0 )
2019 i = points.count() - 1;
2021 maxCount = points.count();
2029 maxCount = points.count() - 1;
2037 maxCount = points.count();
2038 if ( points.first() == points.last() )
2055 renderOffsetVertexAlongLine( points, i, distance, context,
placement );
2062 prevPoint = points.at( 0 );
2064 QPointF symbolPoint;
2065 for ( ; i < maxCount; ++i )
2076 QPointF currentPoint = points.at( i );
2077 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2078 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2081 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2082 currentPoint.x() - prevPoint.x() );
2085 prevPoint = currentPoint;
2089 symbolPoint = points.at( i );
2093 double angle = markerAngle( points, isRing, i );
2098 mFinalVertex = symbolPoint;
2104double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2107 const QPointF &pt = points[vertex];
2109 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2111 int prevIndex = vertex - 1;
2112 int nextIndex = vertex + 1;
2114 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2116 prevIndex = points.count() - 2;
2120 QPointF prevPoint, nextPoint;
2121 while ( prevIndex >= 0 )
2123 prevPoint = points[ prevIndex ];
2124 if ( prevPoint != pt )
2131 while ( nextIndex < points.count() )
2133 nextPoint = points[ nextIndex ];
2134 if ( nextPoint != pt )
2141 if ( prevIndex >= 0 && nextIndex < points.count() )
2143 angle = _averageAngle( prevPoint, pt, nextPoint );
2150 while ( vertex < points.size() - 1 )
2152 const QPointF &nextPt = points[vertex + 1];
2155 angle = MyLine( pt, nextPt ).angle();
2164 while ( vertex >= 1 )
2166 const QPointF &prevPt = points[vertex - 1];
2169 angle = MyLine( prevPt, pt ).angle();
2181 if ( points.isEmpty() )
2191 bool isRing =
false;
2192 if ( points.first() == points.last() )
2194 double angle = markerAngle( points, isRing, vertex );
2197 mFinalVertex = points[vertex];
2203 int pointIncrement = distance > 0 ? 1 : -1;
2204 QPointF previousPoint = points[vertex];
2205 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2206 int endPoint = distance > 0 ? points.count() - 1 : 0;
2207 double distanceLeft = std::fabs( distance );
2209 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2211 const QPointF &pt = points[i];
2213 if ( previousPoint == pt )
2217 MyLine l( previousPoint, pt );
2219 if ( distanceLeft < l.length() )
2222 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2228 mFinalVertex = markerPoint;
2234 distanceLeft -= l.length();
2241void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
double initialLag,
int numberPointsRequired )
2246 QVector< QPointF > points = p;
2247 const bool closedRing = points.first() == points.last();
2249 double lengthLeft = initialOffset;
2251 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2252 if ( initialLagLeft < 0 && closedRing )
2255 QPointF lastPt = points.constLast();
2256 QVector< QPointF > pseudoPoints;
2257 for (
int i = points.count() - 2; i > 0; --i )
2259 if ( initialLagLeft >= 0 )
2264 const QPointF &pt = points[i];
2269 MyLine l( lastPt, pt );
2270 initialLagLeft += l.length();
2275 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2277 points = pseudoPoints;
2282 while ( initialLagLeft < 0 )
2284 dest << points.constFirst();
2285 initialLagLeft += intervalPainterUnits;
2288 if ( initialLag > 0 )
2290 lengthLeft += intervalPainterUnits - initialLagLeft;
2293 QPointF lastPt = points[0];
2294 for (
int i = 1; i < points.count(); ++i )
2296 const QPointF &pt = points[i];
2300 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2309 MyLine l( lastPt, pt );
2310 QPointF diff = l.diffForInterval( intervalPainterUnits );
2314 double c = 1 - lengthLeft / intervalPainterUnits;
2316 lengthLeft += l.length();
2319 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2323 lengthLeft -= intervalPainterUnits;
2326 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2331 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2335 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2342 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2345 while ( dest.size() < numberPointsRequired )
2346 dest << points.constLast();
2350void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver )
2352 if ( !points.isEmpty() )
2356 QPolygonF::const_iterator it = points.constBegin();
2358 for ( ++it; it != points.constEnd(); ++it )
2360 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2361 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2367 const double midPoint = length / 2;
2370 double thisSymbolAngle = 0;
2372 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2374 QVector< QPointF > angleStartPoints;
2375 QVector< QPointF > symbolPoints;
2376 QVector< QPointF > angleEndPoints;
2378 collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
2379 collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
2380 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
2382 pt = symbolPoints.at( 1 );
2383 MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2384 thisSymbolAngle = l.angle();
2389 it = points.constBegin();
2391 qreal last_at = 0, next_at = 0;
2393 for ( ++it; it != points.constEnd(); ++it )
2396 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2397 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2398 if ( next_at >= midPoint )
2405 MyLine l( last, next );
2406 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2407 pt = last + ( next - last ) * k;
2408 thisSymbolAngle = l.angle();
2460 if ( props.contains( QStringLiteral(
"interval" ) ) )
2461 interval = props[QStringLiteral(
"interval" )].toDouble();
2462 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2463 rotate = ( props[QStringLiteral(
"rotate" )].toString() == QLatin1String(
"1" ) );
2465 auto x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2472 return QStringLiteral(
"MarkerLine" );
2492 mMarker->setRenderHints( hints );
2514 toSld( doc, element, context );
2520 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2522 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
2523 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2524 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2525 element.appendChild( symbolizerElem );
2555 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2556 symbolizerElem.appendChild( strokeElem );
2559 QDomElement graphicStrokeElem = doc.createElement( QStringLiteral(
"se:GraphicStroke" ) );
2560 strokeElem.appendChild( graphicStrokeElem );
2565 markerLayer->writeSldMarker( doc, graphicStrokeElem, context );
2569 QgsDebugError( QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) );
2573 QgsDebugError( QStringLiteral(
"Missing marker line symbol layer. Skip it." ) );
2576 if ( !gap.isEmpty() )
2578 QDomElement gapElem = doc.createElement( QStringLiteral(
"se:Gap" ) );
2580 graphicStrokeElem.appendChild( gapElem );
2585 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
2588 symbolizerElem.appendChild( perpOffsetElem );
2598 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2599 if ( strokeElem.isNull() )
2602 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
2603 if ( graphicStrokeElem.isNull() )
2611 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2613 if ( it.key() == QLatin1String(
"placement" ) )
2615 if ( it.value() == QLatin1String(
"points" ) )
2617 else if ( it.value() == QLatin1String(
"firstPoint" ) )
2619 else if ( it.value() == QLatin1String(
"lastPoint" ) )
2621 else if ( it.value() == QLatin1String(
"centralPoint" ) )
2624 else if ( it.value() == QLatin1String(
"rotateMarker" ) )
2630 std::unique_ptr< QgsMarkerSymbol > marker;
2636 layers.append( l.release() );
2644 QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"Gap" ) );
2645 if ( !gapElem.isNull() )
2648 double d = gapElem.firstChild().firstChild().nodeValue().toDouble( &ok );
2654 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
2655 if ( !perpOffsetElem.isNull() )
2658 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2663 double scaleFactor = 1.0;
2664 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
2687 mMarker->setDataDefinedSize( property );
2694 const double prevOpacity =
mMarker->opacity();
2697 mMarker->setOpacity( prevOpacity );
2702 mMarker->setLineAngle( angle );
2720 mMarker->renderPoint( point, feature, context, layer, selected );
2732 return mMarker->size( context );
2738 mMarker->setOutputUnit( unit );
2755 attr.unite(
mMarker->usedAttributes( context ) );
2770 return (
mMarker->size( context ) / 2.0 ) +
2792 if ( props.contains( QStringLiteral(
"interval" ) ) )
2793 interval = props[QStringLiteral(
"interval" )].toDouble();
2794 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2795 rotate = ( props[QStringLiteral(
"rotate" )] == QLatin1String(
"1" ) );
2797 auto x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2799 if ( props.contains( QStringLiteral(
"hash_angle" ) ) )
2801 x->setHashAngle( props[QStringLiteral(
"hash_angle" )].toDouble() );
2804 if ( props.contains( QStringLiteral(
"hash_length" ) ) )
2805 x->setHashLength( props[QStringLiteral(
"hash_length" )].toDouble() );
2807 if ( props.contains( QStringLiteral(
"hash_length_unit" ) ) )
2810 if ( props.contains( QStringLiteral(
"hash_length_map_unit_scale" ) ) )
2818 return QStringLiteral(
"HashLine" );
2827 mHashSymbol->setRenderHints( hints );
2840 map[ QStringLiteral(
"hash_angle" ) ] = QString::number( mHashAngle );
2842 map[QStringLiteral(
"hash_length" )] = QString::number( mHashLength );
2853 x->setHashAngle( mHashAngle );
2854 x->setHashLength( mHashLength );
2855 x->setHashLengthUnit( mHashLengthUnit );
2856 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2862 mHashSymbol->setColor(
color );
2868 return mHashSymbol ? mHashSymbol->color() :
mColor;
2873 return mHashSymbol.get();
2884 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2885 mColor = mHashSymbol->color();
2891 mHashLength =
width;
2906 return ( mHashSymbol->width( context ) / 2.0 )
2914 mHashSymbol->setOutputUnit( unit );
2921 attr.unite( mHashSymbol->usedAttributes( context ) );
2929 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
2938 mHashSymbol->setDataDefinedWidth( property );
2951 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
2956 mSymbolLineAngle = angle;
2961 return mSymbolAngle;
2966 mSymbolAngle = angle;
2971 double lineLength = mHashLength;
2977 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
2991 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
2996 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
3013 const double prevOpacity = mHashSymbol->opacity();
3014 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
3016 mHashSymbol->setOpacity( prevOpacity );
3035 QPolygonF offsetPoints;
3038 renderLine( points, context, patternThickness, patternLength, brush );
3047 renderLine( part, context, patternThickness, patternLength, brush );
3052void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3053 const double patternLength,
const QBrush &sourceBrush )
3059 QBrush brush = sourceBrush;
3064 QPolygonF inputPoints;
3065 inputPoints.reserve( points.size() );
3067 double minX = std::numeric_limits< double >::max();
3068 double minY = std::numeric_limits< double >::max();
3069 double maxX = std::numeric_limits< double >::lowest();
3070 double maxY = std::numeric_limits< double >::lowest();
3072 for (
const QPointF &pt : std::as_const( points ) )
3079 minX = std::min( minX, pt.x() );
3080 minY = std::min( minY, pt.y() );
3081 maxX = std::max( maxX, pt.x() );
3082 maxY = std::max( maxY, pt.y() );
3085 if ( inputPoints.size() < 2 )
3089 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3091 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3094 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3095 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3097 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3098 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3100 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3101 if ( temporaryImage.isNull() )
3110 temporaryImage.fill( Qt::transparent );
3133 QPainterPathStroker stroker;
3134 stroker.setWidth( lineThickness );
3135 stroker.setCapStyle( cap );
3136 stroker.setJoinStyle( join );
3139 path.addPolygon( inputPoints );
3140 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3143 QPainter imagePainter;
3144 imagePainter.begin( &temporaryImage );
3146 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3148 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3149 imagePainter.setPen( Qt::NoPen );
3151 QPointF segmentStartPoint = inputPoints.at( 0 );
3154 double progressThroughImage = 0;
3156 QgsPoint prevSegmentPolygonEndLeft;
3157 QgsPoint prevSegmentPolygonEndRight;
3163 for (
int i = 1; i < inputPoints.size(); ++i )
3168 const QPointF segmentEndPoint = inputPoints.at( i );
3170 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3173 QgsPoint thisSegmentPolygonEndLeft;
3174 QgsPoint thisSegmentPolygonEndRight;
3176 QgsPoint thisSegmentPolygonEndLeftForPainter;
3177 QgsPoint thisSegmentPolygonEndRightForPainter;
3185 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3187 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3188 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3192 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtilsBase::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3193 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3196 const QgsPoint lastSegmentStartPointLeft =
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3197 const QgsPoint lastSegmentEndPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3198 const QgsPoint lastSegmentStartPointRight =
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3199 const QgsPoint lastSegmentEndPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3205 bool isIntersection =
false;
3207 if ( !isIntersection )
3208 prevSegmentPolygonEndLeft = startPointLeft;
3209 isIntersection =
false;
3210 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3211 if ( !isIntersection )
3212 prevSegmentPolygonEndRight = startPointRight;
3214 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3215 startLinePolygonRight = prevSegmentPolygonEndRight;
3219 prevSegmentPolygonEndLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3220 if ( cap != Qt::PenCapStyle::FlatCap )
3221 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3222 prevSegmentPolygonEndRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3223 if ( cap != Qt::PenCapStyle::FlatCap )
3224 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3228 if ( i < inputPoints.size() - 1 )
3233 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3235 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3236 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3241 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3244 const QgsPoint nextSegmentStartPointLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3245 const QgsPoint nextSegmentEndPointLeft =
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3246 const QgsPoint nextSegmentStartPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3247 const QgsPoint nextSegmentEndPointRight =
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3253 bool isIntersection =
false;
3255 if ( !isIntersection )
3256 thisSegmentPolygonEndLeft = endPointLeft;
3257 isIntersection =
false;
3258 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3259 if ( !isIntersection )
3260 thisSegmentPolygonEndRight = endPointRight;
3262 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3263 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3271 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3272 thisSegmentPolygonEndRight = startLinePolygonRight;
3274 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3275 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3279 thisSegmentPolygonEndLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3280 if ( cap != Qt::PenCapStyle::FlatCap )
3281 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3282 thisSegmentPolygonEndRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3283 if ( cap != Qt::PenCapStyle::FlatCap )
3284 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3286 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3287 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3293 QTransform brushTransform;
3294 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3295 brushTransform.rotate( -segmentAngleDegrees );
3296 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3300 brushTransform.translate( -( lineThickness / 2 ), 0 );
3302 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3304 brush.setTransform( brushTransform );
3305 imagePainter.setBrush( brush );
3308 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3309 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3310 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3311 << prevSegmentPolygonEndRight.
toQPointF()
3312 << prevSegmentPolygonEndLeft.
toQPointF() );
3315 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3316 imagePainter.setBrush( Qt::NoBrush );
3317 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3318 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3319 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3320 << prevSegmentPolygonEndRight.
toQPointF()
3321 << prevSegmentPolygonEndLeft.
toQPointF() );
3322 imagePainter.setPen( Qt::NoPen );
3327 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3328 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3329 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3330 progressThroughImage = fmod( progressThroughImage, patternLength );
3333 segmentStartPoint = segmentEndPoint;
3334 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3335 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3343 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3344 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3361 auto res = std::make_unique<QgsRasterLineSymbolLayer>();
3363 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3365 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3367 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3371 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3376 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
3377 res->setPath(
properties[QStringLiteral(
"imageFile" )].toString() );
3379 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3381 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3383 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3387 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3392 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3394 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3397 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
3399 res->setOpacity(
properties[QStringLiteral(
"alpha" )].toDouble() );
3402 return res.release();
3409 map[QStringLiteral(
"imageFile" )] =
mPath;
3411 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3418 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3422 map[QStringLiteral(
"alpha" )] = QString::number(
mOpacity );
3429 auto res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3441 return res.release();
3446 const QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
3447 if ( it !=
properties.end() && it.value().userType() == QMetaType::Type::QString )
3463 return QStringLiteral(
"RasterLine" );
3478 bool cached =
false;
3480 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3481 static_cast< int >( std::ceil( scaledHeight ) ) ),
3506 double strokeWidth =
mWidth;
3523 bool cached =
false;
3525 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3526 static_cast< int >( std::ceil( scaledHeight ) ) ),
3531 if ( useSelectedColor )
3536 const QBrush brush( sourceImage );
3606 auto res = std::make_unique<QgsLineburstSymbolLayer>();
3608 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3610 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3612 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3616 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3621 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3623 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3625 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3629 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3634 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3636 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3639 if (
properties.contains( QStringLiteral(
"color_type" ) ) )
3642 if (
properties.contains( QStringLiteral(
"color" ) ) )
3646 if (
properties.contains( QStringLiteral(
"gradient_color2" ) ) )
3661 return res.release();
3668 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3675 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3681 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
3692 auto res = std::make_unique< QgsLineburstSymbolLayer >();
3708 return res.release();
3713 return QStringLiteral(
"Lineburst" );
3734 double strokeWidth =
mWidth;
3750 if ( useSelectedColor )
3754 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3765 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3777 gradient.setColorAt( 0.0, color1 );
3778 gradient.setColorAt( 1.0,
color2 );
3780 const QBrush brush( gradient );
3859 if ( props.contains( QStringLiteral(
"line_width" ) ) )
3861 width = props[QStringLiteral(
"line_width" )].toDouble();
3863 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
3865 width = props[QStringLiteral(
"outline_width" )].toDouble();
3867 else if ( props.contains( QStringLiteral(
"width" ) ) )
3869 width = props[QStringLiteral(
"width" )].toDouble();
3874 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
3878 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
3882 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
3887 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3889 if ( props.contains( QStringLiteral(
"offset" ) ) )
3890 l->setOffset( props[QStringLiteral(
"offset" )].toDouble() );
3891 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
3893 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3895 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
3897 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
3900 l->restoreOldDataDefinedProperties( props );
3907 return QStringLiteral(
"FilledLine" );
3956 Qt::PenJoinStyle join = mPenJoinStyle;
3965 Qt::PenCapStyle cap = mPenCapStyle;
3981 const double prevOpacity = mFill->opacity();
3982 mFill->setOpacity( mFill->opacity() * context.
opacity() );
3989 if ( points.count() >= 2 )
3992 geos::unique_ptr lineGeom;
4007 auto inputPoly = std::make_unique< QgsPolygon >(
static_cast< QgsLineString *
>( ls.release() ) );
4013 if ( !parts.empty() )
4035 geos::unique_ptr buffered =
QgsGeos::buffer( lineGeom.get(), scaledWidth / 2, 8,
4041 std::unique_ptr< QgsAbstractGeometry > bufferedGeom =
QgsGeos::fromGeos( buffered.get() );
4043 for (
const QList< QPolygonF > &polygon : parts )
4045 QVector< QPolygonF > rings;
4046 for (
int i = 1; i < polygon.size(); ++i )
4047 rings << polygon.at( i );
4048 mFill->renderPolygon( polygon.value( 0 ), &rings, context.
feature(), context.
renderContext(), -1, useSelectedColor );
4056 mFill->setOpacity( prevOpacity );
4063 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
4068 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
4083 res->setSubSymbol( mFill->clone() );
4084 return res.release();
4119 attr.unite( mFill->usedAttributes( context ) );
4127 if ( mFill && mFill->hasDataDefinedProperties() )
4136 mFill->setColor(
c );
4141 return mFill ? mFill->color() :
mColor;
4148 || ( mFill && mFill->usesMapUnits() );
4155 mFill->setMapUnitScale( scale );
4162 return mFill->mapUnitScale();
4171 mFill->setOutputUnit( unit );
4178 return mFill->outputUnit();
MarkerLinePlacement
Defines how/where the symbols should be placed on a line.
@ CurvePoint
Place symbols at every virtual curve point in the line (used when rendering curved geometry types onl...
@ InnerVertices
Inner vertices (i.e. all vertices except the first and last vertex)
@ LastVertex
Place symbols on the last vertex in the line.
@ CentralPoint
Place symbols at the mid point of the line.
@ SegmentCenter
Place symbols at the center of every line segment.
@ Vertex
Place symbols on every vertex in the line.
@ Interval
Place symbols at regular intervals.
@ FirstVertex
Place symbols on the first vertex in the line.
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
@ IsSymbolLayerSubSymbol
Symbol is being rendered as a sub-symbol of a QgsSymbolLayer.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
GradientColorSource
Gradient color sources.
@ ColorRamp
Gradient color ramp.
@ CanCalculateMaskGeometryPerFeature
If present, indicates that mask geometry can safely be calculated per feature for the symbol layer....
@ Curve
An intermediate point on a segment defining the curvature of the segment.
@ Segment
The actual start or end point of a segment.
QFlags< SymbolLayerFlag > SymbolLayerFlags
Symbol layer flags.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
@ Miter
Use mitered joins.
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.
@ Flat
Flat cap (in line with start/end of line)
@ 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.
@ MultiLineString
MultiLineString.
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 std::unique_ptr< 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.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
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.
A geometry is the spatial representation of a feature.
QVector< QgsGeometry > coerceToType(Qgis::WkbType type, double defaultZ=0, double defaultM=0, bool avoidDuplicates=true) const
Attempts to coerce this geometry into the specified destination type.
static geos::unique_ptr offsetCurve(const GEOSGeometry *geometry, double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg=nullptr)
Directly calculates the offset curve for a GEOS geometry object and returns a GEOS geometry result.
QgsAbstractGeometry * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlags())
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
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.
Line string geometry type, with support for z-dimension and m-values.
static std::unique_ptr< QgsLineString > fromQPolygonF(const QPolygonF &polygon)
Returns a new linestring from a QPolygonF polygon input.
Abstract base class for line symbol layers.
Qgis::RenderUnit mOffsetUnit
RenderRingFilter
Options for filtering rings when the line symbol layer is being used to render a polygon's rings.
@ ExteriorRingOnly
Render the exterior ring only.
@ InteriorRingsOnly
Render the interior rings only.
@ AllRings
Render both exterior and interior rings.
QgsMapUnitScale mWidthMapUnitScale
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void setWidthMapUnitScale(const QgsMapUnitScale &scale)
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit mWidthUnit
void setOffset(double offset)
Sets the line's offset.
RenderRingFilter mRingFilter
void setOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the line's offset.
void setWidthUnit(Qgis::RenderUnit unit)
Sets the units for the line's width.
virtual double width() const
Returns the estimated width for the line symbol layer.
QgsMapUnitScale mOffsetMapUnitScale
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the line's offset.
QgsMapUnitScale mapUnitScale() const override
void setRingFilter(QgsLineSymbolLayer::RenderRingFilter filter)
Sets the line symbol layer's ring filter, which controls which rings are rendered when the line symbo...
void setMapUnitScale(const QgsMapUnitScale &scale) override
double offset() const
Returns the line's offset.
Qgis::RenderUnit offsetUnit() const
Returns the units for the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
Line symbol layer type which draws a gradient pattern perpendicularly along a line.
std::unique_ptr< QgsColorRamp > mGradientRamp
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp used for the gradient line.
QColor color2() const
Returns the color for endpoint of gradient, only used if the gradient color type is set to SimpleTwoC...
Qgis::GradientColorSource mGradientColorType
QString layerType() const override
Returns a string that represents this layer type.
~QgsLineburstSymbolLayer() override
QgsLineburstSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsMapUnitScale mapUnitScale() const override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsLineburstSymbolLayer, using the settings serialized in the properties map (correspon...
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QgsLineburstSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, const QColor &color2=Qt::white)
Constructor for QgsLineburstSymbolLayer, with the specified start and end gradient colors.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsColorRamp * colorRamp()
Returns the color ramp used for the gradient line.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
void transformInPlace(double &x, double &y) const
Transforms map coordinates to device coordinates.
Struct for storing maximum and minimum scales for measurements in map units.
Line symbol layer type which draws repeating marker symbols along a line feature.
Q_DECL_DEPRECATED bool rotateMarker() const
Shall the marker be rotated.
std::unique_ptr< QgsMarkerSymbol > mMarker
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsMarkerLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
double width() const override
Returns the estimated width for the line symbol layer.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsMarkerLineSymbolLayer, using the settings serialized in the properties map (correspo...
QgsMarkerLineSymbolLayer(bool rotateMarker=DEFAULT_MARKERLINE_ROTATE, double interval=DEFAULT_MARKERLINE_INTERVAL)
Constructor for QgsMarkerLineSymbolLayer.
void setWidth(double width) override
Sets the width of the line symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
Q_DECL_DEPRECATED 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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Resolves relative paths into absolute paths and vice versa.
QgsPointXY project(double distance, double bearing) const
Returns a new point which corresponds to this point projected by a specified distance in a specified ...
Point geometry type, with support for z-dimension and m-values.
QPointF toQPointF() const
Returns the point as a QPointF.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const final
Returns the calculated value of the property with the specified key from within the collection.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
A store for object properties.
Line symbol layer type which draws line sections using a raster image file.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QgsRasterLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
double opacity() const
Returns the line opacity.
QString path() const
Returns the raster image path.
void setPath(const QString &path)
Set the raster image path.
QString layerType() const override
Returns a string that represents this layer type.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
QgsRasterLineSymbolLayer(const QString &path=QString())
Constructor for QgsRasterLineSymbolLayer, with the specified raster image path.
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsRasterLineSymbolLayer, using the settings serialized in the properties map (correspo...
QColor color() const override
Returns the "representative" color of the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsMapUnitScale mapUnitScale() const override
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
virtual ~QgsRasterLineSymbolLayer()
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
QgsVectorSimplifyMethod & vectorSimplifyMethod()
Returns the simplification settings to use when rendering vector layers.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QColor selectionColor() const
Returns the color to use when rendering selected features.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
const QgsAbstractGeometry * geometry() const
Returns pointer to the unsegmentized geometry.
Scoped object for saving and restoring a QPainter object's state.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void setDrawInsidePolygon(bool drawInsidePolygon)
Sets whether the line should only be drawn inside polygons, and any portion of the line which falls o...
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QgsMapUnitScale mapUnitScale() const override
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QVector< qreal > customDashVector() const
Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the outline of polygon, using the given render context.
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
void setCustomDashPatternMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for lengths used in the custom dash pattern.
void setTrimDistanceEndMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the end of the line.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void setTrimDistanceEnd(double distance)
Sets the trim distance for the end of the line, which dictates a length from the end of the line at w...
double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets offset.
QgsSimpleLineSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, double width=DEFAULT_SIMPLELINE_WIDTH, Qt::PenStyle penStyle=DEFAULT_SIMPLELINE_PENSTYLE)
Constructor for QgsSimpleLineSymbolLayer.
~QgsSimpleLineSymbolLayer() override
void setUseCustomDashPattern(bool b)
Sets whether the line uses a custom dash pattern.
void setTweakDashPatternOnCorners(bool enabled)
Sets whether dash patterns tweaks should be applied on sharp corners, to ensure that a double-length ...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
void setCustomDashVector(const QVector< qreal > &vector)
Sets the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ren...
void setDashPatternOffset(double offset)
Sets the dash pattern offset, which dictates how far along the dash pattern the pattern should start ...
QColor dxfColor(QgsSymbolRenderContext &context) const override
Gets color.
QString layerType() const override
Returns a string that represents this layer type.
void setDashPatternOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the dash pattern offset.
QgsSimpleLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
void setAlignDashPattern(bool enabled)
Sets whether dash patterns should be aligned to the start and end of lines, by applying subtle tweaks...
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleLineSymbolLayer from an SLD XML DOM element.
double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets line width.
void setTrimDistanceStartMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the start of the line.
QVector< qreal > dxfCustomDashPattern(Qgis::RenderUnit &unit) const override
Gets dash pattern.
Qt::PenCapStyle penCapStyle() const
Returns the pen cap style used to render the line (e.g.
void setTrimDistanceEndUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the end of the line.
void setDashPatternOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the dash pattern offset.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
Q_DECL_DEPRECATED 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.
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void setExtraProperties(const QVariantMap &properties)
Sets the open ended set of properties that can drive/inform the SLD encoding.
QVariantMap extraProperties() const
Returns the open ended set of properties that can drive/inform the SLD encoding.
static QString encodePenStyle(Qt::PenStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static Q_DECL_DEPRECATED 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 std::unique_ptr< QgsSymbolLayer > createMarkerLayerFromSld(QDomElement &element)
Creates a new marker layer from a SLD DOM element.
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 QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
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 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 Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
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 Q_DECL_DEPRECATED void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
Creates an SLD geometry element.
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static Qt::PenStyle decodePenStyle(const QString &str)
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
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 void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, QgsSldExportContext &context, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QString encodeRealVector(const QVector< qreal > &v)
Abstract base class for symbol layers.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
bool shouldRenderUsingSelectionColor(const QgsSymbolRenderContext &context) const
Returns true if the symbol layer should be rendered using the selection color from the render context...
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
bool installMasks(QgsRenderContext &context, bool recursive, const QRectF &rect=QRectF())
When rendering, install masks on context painter.
void removeMasks(QgsRenderContext &context, bool recursive)
When rendering, remove previously installed masks from context painter if recursive is true masks are...
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
Property
Data definable properties.
@ SecondaryColor
Secondary color (eg for gradient fills)
@ File
Filename, eg for svg files.
@ DashPatternOffset
Dash pattern offset,.
@ OffsetAlongLine
Offset along line.
@ CustomDash
Custom dash pattern.
@ StrokeStyle
Stroke style (eg solid, dashed)
@ StrokeColor
Stroke color.
@ TrimStart
Trim distance from start of line.
@ CapStyle
Line cap style.
@ Placement
Line marker placement.
@ LineAngle
Line angle, or angle of hash lines for hash line symbols.
@ JoinStyle
Line join style.
@ AverageAngleLength
Length to average symbol angles over.
@ Interval
Line marker interval.
@ StrokeWidth
Stroke width.
@ LineDistance
Distance between lines, or length of lines for hash line symbols.
@ TrimEnd
Trim distance from end of line.
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
virtual Qgis::SymbolLayerFlags flags() const
Returns flags which control the symbol layer's behavior.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
Encapsulates the context in which a symbol is being rendered.
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)
#define QgsDebugError(str)
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.