37#include <QDomDocument>
43 : mPenStyle( penStyle )
47 mCustomDashVector << 5 << 2;
57 mCustomDashPatternUnit = unit;
58 mDashPatternOffsetUnit = unit;
59 mTrimDistanceStartUnit = unit;
60 mTrimDistanceEndUnit = unit;
84 mCustomDashPatternMapUnitScale = scale;
104 if ( props.contains( QStringLiteral(
"line_color" ) ) )
108 else if ( props.contains( QStringLiteral(
"outline_color" ) ) )
112 else if ( props.contains( QStringLiteral(
"color" ) ) )
117 if ( props.contains( QStringLiteral(
"line_width" ) ) )
119 width = props[QStringLiteral(
"line_width" )].toDouble();
121 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
123 width = props[QStringLiteral(
"outline_width" )].toDouble();
125 else if ( props.contains( QStringLiteral(
"width" ) ) )
128 width = props[QStringLiteral(
"width" )].toDouble();
130 if ( props.contains( QStringLiteral(
"line_style" ) ) )
134 else if ( props.contains( QStringLiteral(
"outline_style" ) ) )
138 else if ( props.contains( QStringLiteral(
"penstyle" ) ) )
144 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
148 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
152 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
157 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
159 if ( props.contains( QStringLiteral(
"offset" ) ) )
160 l->
setOffset( props[QStringLiteral(
"offset" )].toDouble() );
161 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
163 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
165 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
167 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
170 if ( props.contains( QStringLiteral(
"use_custom_dash" ) ) )
174 if ( props.contains( QStringLiteral(
"customdash" ) ) )
178 if ( props.contains( QStringLiteral(
"customdash_unit" ) ) )
182 if ( props.contains( QStringLiteral(
"customdash_map_unit_scale" ) ) )
187 if ( props.contains( QStringLiteral(
"draw_inside_polygon" ) ) )
192 if ( props.contains( QStringLiteral(
"ring_filter" ) ) )
197 if ( props.contains( QStringLiteral(
"dash_pattern_offset" ) ) )
199 if ( props.contains( QStringLiteral(
"dash_pattern_offset_unit" ) ) )
201 if ( props.contains( QStringLiteral(
"dash_pattern_offset_map_unit_scale" ) ) )
204 if ( props.contains( QStringLiteral(
"trim_distance_start" ) ) )
206 if ( props.contains( QStringLiteral(
"trim_distance_start_unit" ) ) )
208 if ( props.contains( QStringLiteral(
"trim_distance_start_map_unit_scale" ) ) )
210 if ( props.contains( QStringLiteral(
"trim_distance_end" ) ) )
212 if ( props.contains( QStringLiteral(
"trim_distance_end_unit" ) ) )
214 if ( props.contains( QStringLiteral(
"trim_distance_end_map_unit_scale" ) ) )
217 if ( props.contains( QStringLiteral(
"align_dash_pattern" ) ) )
220 if ( props.contains( QStringLiteral(
"tweak_dash_pattern_on_corners" ) ) )
230 return QStringLiteral(
"SimpleLine" );
237 mPen.setColor( penColor );
239 mPen.setWidthF( scaledWidth );
243 const double dashWidthDiv = std::max( 1.0, scaledWidth );
244 if ( mUseCustomDashPattern )
246 mPen.setStyle( Qt::CustomDashLine );
250 QVector<qreal> scaledVector;
251 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
252 for ( ; it != mCustomDashVector.constEnd(); ++it )
257 mPen.setDashPattern( scaledVector );
261 mPen.setStyle( mPenStyle );
264 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
269 mPen.setJoinStyle( mPenJoinStyle );
270 mPen.setCapStyle( mPenCapStyle );
275 selColor.setAlphaF( context.
opacity() );
276 mSelPen.setColor( selColor );
293 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
300 if ( mDrawInsidePolygon )
308 if ( mDrawInsidePolygon )
311 QPainterPath clipPath;
312 clipPath.addPolygon( points );
317 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
319 QPolygonF ring = *it;
320 clipPath.addPolygon( ring );
325 p->setClipPath( clipPath, Qt::IntersectClip );
348 for (
const QPolygonF &ring : std::as_const( *rings ) )
364 if ( mDrawInsidePolygon )
380 QPolygonF points = pts;
382 double startTrim = mTrimDistanceStart;
388 double endTrim = mTrimDistanceEnd;
395 double totalLength = -1;
399 startTrim = startTrim * 0.01 * totalLength;
407 if ( totalLength < 0 )
409 endTrim = endTrim * 0.01 * totalLength;
422 mPen.setColor( penColor );
425 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
428 const QPen pen = useSelectedColor ? mSelPen : mPen;
430 if ( !pen.dashPattern().isEmpty() )
433 const QVector<double> pattern = pen.dashPattern();
434 bool foundNonNull =
false;
435 for (
int i = 0; i < pattern.size(); ++i )
447 p->setBrush( Qt::NoBrush );
450 std::unique_ptr< QgsScopedQPainterState > painterState;
451 if ( points.size() <= 2 &&
454 ( p->renderHints() & QPainter::Antialiasing ) )
456 painterState = std::make_unique< QgsScopedQPainterState >( p );
457 p->setRenderHint( QPainter::Antialiasing,
false );
460 const bool applyPatternTweaks = mAlignDashPattern
461 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
462 && pen.dashOffset() == 0;
466 if ( applyPatternTweaks )
468 drawPathWithDashPatternTweaks( p, points, pen );
474 path.addPolygon( points );
489 for (
const QPolygonF &part : mline )
491 if ( applyPatternTweaks )
493 drawPathWithDashPatternTweaks( p, part, pen );
499 path.addPolygon( part );
510 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
516 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
519 map[QStringLiteral(
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
523 map[QStringLiteral(
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
526 map[QStringLiteral(
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
529 map[QStringLiteral(
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
532 map[QStringLiteral(
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
533 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
534 map[QStringLiteral(
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
535 map[QStringLiteral(
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
574 if ( mPenStyle == Qt::NoPen )
577 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
578 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
579 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
580 element.appendChild( symbolizerElem );
586 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
587 symbolizerElem.appendChild( strokeElem );
589 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
598 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
601 symbolizerElem.appendChild( perpOffsetElem );
607 if ( mUseCustomDashPattern )
610 mPen.color(), mPenJoinStyle,
611 mPenCapStyle,
mOffset, &mCustomDashVector );
624 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
625 if ( strokeElem.isNull() )
642 QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
643 if ( !perpOffsetElem.isNull() )
646 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
651 double scaleFactor = 1.0;
652 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
667void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
673 bool hasStrokeWidthExpression =
false;
680 pen.setWidthF( scaledWidth );
681 selPen.setWidthF( scaledWidth );
682 hasStrokeWidthExpression =
true;
691 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
692 pen.setColor( penColor );
706 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
710 QVector<qreal> dashVector;
714 QStringList dashList = exprVal.toString().split(
';' );
715 QStringList::const_iterator dashIt = dashList.constBegin();
716 for ( ; dashIt != dashList.constEnd(); ++dashIt )
720 pen.setDashPattern( dashVector );
727 QVector<qreal> scaledVector;
728 for (
double v : std::as_const( mCustomDashVector ) )
733 mPen.setDashPattern( scaledVector );
737 double patternOffset = mDashPatternOffset;
773void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
775 if ( pen.dashPattern().empty() || points.size() < 2 )
778 QVector< qreal > sourcePattern = pen.dashPattern();
779 const double dashWidthDiv = std::max( 1.0001, pen.widthF() );
781 for (
int i = 0; i < sourcePattern.size(); ++ i )
782 sourcePattern[i] *= pen.widthF();
784 if ( pen.widthF() <= 1.0 )
785 pen.setWidthF( 1.0001 );
787 QVector< qreal > buffer;
788 QPolygonF bufferedPoints;
789 QPolygonF previousSegmentBuffer;
794 auto ptIt = points.constBegin();
795 double totalBufferLength = 0;
796 int patternIndex = 0;
797 double currentRemainingDashLength = 0;
798 double currentRemainingGapLength = 0;
800 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
802 QVector< qreal > result;
803 result.reserve( buffer.size() );
804 for (
auto it = buffer.begin(); it != buffer.end(); )
808 while ( dash == 0 && !result.empty() )
810 result.last() += gap;
812 if ( it == buffer.end() )
817 while ( gap == 0 && it != buffer.end() )
822 result << dash << gap;
827 double currentBufferLineLength = 0;
828 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
829 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
831 if ( buffer.empty() || bufferedPoints.size() < 2 )
836 if ( currentRemainingDashLength )
839 buffer << currentRemainingDashLength << 0.0;
840 totalBufferLength += currentRemainingDashLength;
842 QVector< qreal > compressed = compressPattern( buffer );
843 if ( !currentRemainingDashLength )
846 totalBufferLength -= compressed.last();
847 compressed.last() = 0;
851 const double scaleFactor = currentBufferLineLength / totalBufferLength;
853 bool shouldFlushPreviousSegmentBuffer =
false;
855 if ( !previousSegmentBuffer.empty() )
859 if ( !firstDashSubstring.empty() )
865 compressed = compressed.mid( 2 );
866 shouldFlushPreviousSegmentBuffer = !compressed.empty();
869 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
871 QPen adjustedPen = pen;
872 adjustedPen.setStyle( Qt::SolidLine );
873 painter->setPen( adjustedPen );
875 path.addPolygon( previousSegmentBuffer );
876 painter->drawPath( path );
877 previousSegmentBuffer.clear();
880 double finalDash = 0;
887 if ( !compressed.empty() )
889 finalDash = compressed.at( compressed.size() - 2 );
890 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
892 const QPolygonF thisPoints = bufferedPoints;
898 previousSegmentBuffer << bufferedPoints;
902 currentBufferLineLength = 0;
903 currentRemainingDashLength = 0;
904 currentRemainingGapLength = 0;
905 totalBufferLength = 0;
908 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
910 QPen adjustedPen = pen;
911 if ( !compressed.empty() )
914 compressed = compressed.mid( 0, 32 );
915 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
916 adjustedPen.setDashPattern( compressed );
920 adjustedPen.setStyle( Qt::SolidLine );
923 painter->setPen( adjustedPen );
925 path.addPolygon( bufferedPoints );
926 painter->drawPath( path );
929 bufferedPoints.clear();
935 bufferedPoints << p2;
936 for ( ; ptIt != points.constEnd(); ++ptIt )
944 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
945 currentBufferLineLength += remainingSegmentDistance;
949 if ( currentRemainingDashLength > 0 )
952 if ( remainingSegmentDistance >= currentRemainingDashLength )
955 buffer << currentRemainingDashLength << 0.0;
956 totalBufferLength += currentRemainingDashLength;
957 remainingSegmentDistance -= currentRemainingDashLength;
959 currentRemainingDashLength = 0.0;
960 currentRemainingGapLength = sourcePattern.at( patternIndex );
965 buffer << remainingSegmentDistance << 0.0;
966 totalBufferLength += remainingSegmentDistance;
967 currentRemainingDashLength -= remainingSegmentDistance;
971 if ( currentRemainingGapLength > 0 )
974 if ( remainingSegmentDistance >= currentRemainingGapLength )
977 buffer << 0.0 << currentRemainingGapLength;
978 totalBufferLength += currentRemainingGapLength;
979 remainingSegmentDistance -= currentRemainingGapLength;
980 currentRemainingGapLength = 0.0;
986 buffer << 0.0 << remainingSegmentDistance;
987 totalBufferLength += remainingSegmentDistance;
988 currentRemainingGapLength -= remainingSegmentDistance;
993 if ( patternIndex >= sourcePattern.size() )
996 const double nextPatternDashLength = sourcePattern.at( patternIndex );
997 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
998 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1000 buffer << nextPatternDashLength << nextPatternGapLength;
1001 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1002 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1005 else if ( nextPatternDashLength <= remainingSegmentDistance )
1008 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1009 totalBufferLength += remainingSegmentDistance;
1010 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1011 currentRemainingDashLength = 0;
1018 buffer << remainingSegmentDistance << 0.0;
1019 totalBufferLength += remainingSegmentDistance;
1020 currentRemainingGapLength = 0;
1021 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1026 bufferedPoints << p1;
1027 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1029 QPointF nextPoint = *( ptIt + 1 );
1035 flushBuffer( &nextPoint );
1036 bufferedPoints << p1;
1039 if ( patternIndex % 2 == 1 )
1043 currentRemainingDashLength = sourcePattern.at( patternIndex );
1050 flushBuffer(
nullptr );
1051 if ( !previousSegmentBuffer.empty() )
1053 QPen adjustedPen = pen;
1054 adjustedPen.setStyle( Qt::SolidLine );
1055 painter->setPen( adjustedPen );
1057 path.addPolygon( previousSegmentBuffer );
1058 painter->drawPath( path );
1059 previousSegmentBuffer.clear();
1065 if ( mDrawInsidePolygon )
1079 unit = mCustomDashPatternUnit;
1080 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1117 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1122 return mAlignDashPattern;
1132 return mPatternCartographicTweakOnSharpCorners;
1137 mPatternCartographicTweakOnSharpCorners =
enabled;
1165 MyLine( QPointF p1, QPointF p2 )
1166 : mVertical( false )
1167 , mIncreasing( false )
1179 mIncreasing = ( p2.y() > p1.y() );
1184 mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
1185 mIncreasing = ( p2.x() > p1.x() );
1189 double x = ( p2.x() - p1.x() );
1190 double y = ( p2.y() - p1.y() );
1191 mLength = std::sqrt( x * x + y * y );
1197 double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
1205 QPointF diffForInterval(
double interval )
1208 return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
1210 double alpha = std::atan( mT );
1211 double dx = std::cos( alpha ) * interval;
1212 double dy = std::sin( alpha ) * interval;
1213 return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
1216 double length()
const {
return mLength; }
1231 : mRotateSymbols( rotateSymbol )
1232 , mInterval( interval )
1271 if ( mRenderingFeature )
1275 mFeatureSymbolOpacity = context.
opacity();
1276 mCurrentFeatureIsSelected = useSelectedColor;
1294 QString placementString = exprVal.toString();
1295 if ( placementString.compare( QLatin1String(
"interval" ), Qt::CaseInsensitive ) == 0 )
1299 else if ( placementString.compare( QLatin1String(
"vertex" ), Qt::CaseInsensitive ) == 0 )
1303 else if ( placementString.compare( QLatin1String(
"innervertices" ), Qt::CaseInsensitive ) == 0 )
1307 else if ( placementString.compare( QLatin1String(
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
1311 else if ( placementString.compare( QLatin1String(
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
1315 else if ( placementString.compare( QLatin1String(
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
1319 else if ( placementString.compare( QLatin1String(
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
1323 else if ( placementString.compare( QLatin1String(
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
1336 double averageOver = mAverageAngleLength;
1347 renderPolylineInterval( points, context, averageOver );
1349 renderPolylineCentral( points, context, averageOver );
1353 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1356 mHasRenderedFirstPart = mRenderingFeature;
1372 for (
int part = 0; part < mline.count(); ++part )
1374 const QPolygonF &points2 = mline[ part ];
1377 renderPolylineInterval( points2, context, averageOver );
1379 renderPolylineCentral( points2, context, averageOver );
1387 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1390 mHasRenderedFirstPart = mRenderingFeature;
1410 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1440 for (
int i = 0; i < rings->size(); ++i )
1473 mIntervalUnit = unit;
1474 mOffsetAlongLineUnit = unit;
1475 mAverageAngleLengthUnit = unit;
1500 map[QStringLiteral(
"rotate" )] = (
rotateSymbols() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1501 map[QStringLiteral(
"interval" )] = QString::number(
interval() );
1502 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
1503 map[QStringLiteral(
"offset_along_line" )] = QString::number(
offsetAlongLine() );
1510 map[QStringLiteral(
"average_angle_length" )] = QString::number( mAverageAngleLength );
1516 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
1517 map[QStringLiteral(
"place_on_every_part" )] = mPlaceOnEveryPart;
1523 return mPlaceOnEveryPart
1531 mRenderingFeature =
true;
1532 mHasRenderedFirstPart =
false;
1537 mRenderingFeature =
false;
1545 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1546 mFeatureSymbolOpacity = 1;
1573 if (
properties.contains( QStringLiteral(
"offset" ) ) )
1577 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
1581 if (
properties.contains( QStringLiteral(
"interval_unit" ) ) )
1585 if (
properties.contains( QStringLiteral(
"offset_along_line" ) ) )
1589 if (
properties.contains( QStringLiteral(
"offset_along_line_unit" ) ) )
1593 if (
properties.contains( ( QStringLiteral(
"offset_along_line_map_unit_scale" ) ) ) )
1598 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1602 if (
properties.contains( QStringLiteral(
"interval_map_unit_scale" ) ) )
1607 if (
properties.contains( QStringLiteral(
"average_angle_length" ) ) )
1611 if (
properties.contains( QStringLiteral(
"average_angle_unit" ) ) )
1615 if (
properties.contains( ( QStringLiteral(
"average_angle_map_unit_scale" ) ) ) )
1620 if (
properties.contains( QStringLiteral(
"placement" ) ) )
1622 if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"vertex" ) )
1624 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"lastvertex" ) )
1626 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"firstvertex" ) )
1628 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"centralpoint" ) )
1630 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"curvepoint" ) )
1632 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"segmentcenter" ) )
1637 else if (
properties.contains( QStringLiteral(
"placements" ) ) )
1643 if (
properties.contains( QStringLiteral(
"ring_filter" ) ) )
1653void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver )
1655 if ( points.isEmpty() )
1659 double lengthLeft = 0;
1691 if ( painterUnitInterval < 0 )
1694 double painterUnitOffsetAlongLine = 0;
1697 double totalLength = -1;
1718 if ( points.isClosed() )
1720 if ( painterUnitOffsetAlongLine > 0 )
1722 if ( totalLength < 0 )
1724 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1726 else if ( painterUnitOffsetAlongLine < 0 )
1728 if ( totalLength < 0 )
1730 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1742 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1744 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1746 QVector< QPointF > angleStartPoints;
1747 QVector< QPointF > symbolPoints;
1748 QVector< QPointF > angleEndPoints;
1756 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
1758 if ( symbolPoints.empty() )
1764 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1767 symbolPoints.pop_back();
1770 angleEndPoints.reserve( symbolPoints.size() );
1771 angleStartPoints.reserve( symbolPoints.size() );
1772 if ( averageOver <= painterUnitOffsetAlongLine )
1774 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
1778 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1780 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
1783 for (
int i = 0; i < symbolPoints.size(); ++ i )
1788 const QPointF pt = symbolPoints[i];
1789 const QPointF startPt = angleStartPoints[i];
1790 const QPointF endPt = angleEndPoints[i];
1792 MyLine l( startPt, endPt );
1807 QPointF lastPt = points[0];
1808 for (
int i = 1; i < points.count(); ++i )
1813 const QPointF &pt = points[i];
1819 MyLine l( lastPt, pt );
1820 QPointF diff = l.diffForInterval( painterUnitInterval );
1824 double c = 1 - lengthLeft / painterUnitInterval;
1826 lengthLeft += l.length();
1835 while ( lengthLeft > painterUnitInterval )
1839 lengthLeft -= painterUnitInterval;
1851static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1854 double a1 = MyLine( prevPt, pt ).angle();
1855 double a2 = MyLine( pt, nextPt ).angle();
1856 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1858 return std::atan2( unitY, unitX );
1863 if ( points.isEmpty() )
1868 int i = -1, maxCount = 0;
1869 bool isRing =
false;
1883 double totalLength = -1;
1903 if ( points.isClosed() )
1907 if ( totalLength < 0 )
1913 if ( totalLength < 0 )
1987 i = points.count() - 1;
1989 maxCount = points.count();
1997 maxCount = points.count() - 1;
2005 maxCount = points.count();
2006 if ( points.first() == points.last() )
2023 renderOffsetVertexAlongLine( points, i, distance, context,
placement );
2030 prevPoint = points.at( 0 );
2032 QPointF symbolPoint;
2033 for ( ; i < maxCount; ++i )
2044 QPointF currentPoint = points.at( i );
2045 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2046 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2049 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2050 currentPoint.x() - prevPoint.x() );
2053 prevPoint = currentPoint;
2057 symbolPoint = points.at( i );
2061 double angle = markerAngle( points, isRing, i );
2066 mFinalVertex = symbolPoint;
2072double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2075 const QPointF &pt = points[vertex];
2077 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2079 int prevIndex = vertex - 1;
2080 int nextIndex = vertex + 1;
2082 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2084 prevIndex = points.count() - 2;
2088 QPointF prevPoint, nextPoint;
2089 while ( prevIndex >= 0 )
2091 prevPoint = points[ prevIndex ];
2092 if ( prevPoint != pt )
2099 while ( nextIndex < points.count() )
2101 nextPoint = points[ nextIndex ];
2102 if ( nextPoint != pt )
2109 if ( prevIndex >= 0 && nextIndex < points.count() )
2111 angle = _averageAngle( prevPoint, pt, nextPoint );
2118 while ( vertex < points.size() - 1 )
2120 const QPointF &nextPt = points[vertex + 1];
2123 angle = MyLine( pt, nextPt ).angle();
2132 while ( vertex >= 1 )
2134 const QPointF &prevPt = points[vertex - 1];
2137 angle = MyLine( prevPt, pt ).angle();
2149 if ( points.isEmpty() )
2159 bool isRing =
false;
2160 if ( points.first() == points.last() )
2162 double angle = markerAngle( points, isRing, vertex );
2165 mFinalVertex = points[vertex];
2171 int pointIncrement = distance > 0 ? 1 : -1;
2172 QPointF previousPoint = points[vertex];
2173 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2174 int endPoint = distance > 0 ? points.count() - 1 : 0;
2175 double distanceLeft = std::fabs( distance );
2177 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2179 const QPointF &pt = points[i];
2181 if ( previousPoint == pt )
2185 MyLine l( previousPoint, pt );
2187 if ( distanceLeft < l.length() )
2190 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2196 mFinalVertex = markerPoint;
2202 distanceLeft -= l.length();
2209void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
double initialLag,
int numberPointsRequired )
2214 QVector< QPointF > points = p;
2215 const bool closedRing = points.first() == points.last();
2217 double lengthLeft = initialOffset;
2219 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2220 if ( initialLagLeft < 0 && closedRing )
2223 QPointF lastPt = points.constLast();
2224 QVector< QPointF > pseudoPoints;
2225 for (
int i = points.count() - 2; i > 0; --i )
2227 if ( initialLagLeft >= 0 )
2232 const QPointF &pt = points[i];
2237 MyLine l( lastPt, pt );
2238 initialLagLeft += l.length();
2243 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2245 points = pseudoPoints;
2250 while ( initialLagLeft < 0 )
2252 dest << points.constFirst();
2253 initialLagLeft += intervalPainterUnits;
2256 if ( initialLag > 0 )
2258 lengthLeft += intervalPainterUnits - initialLagLeft;
2261 QPointF lastPt = points[0];
2262 for (
int i = 1; i < points.count(); ++i )
2264 const QPointF &pt = points[i];
2268 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2277 MyLine l( lastPt, pt );
2278 QPointF diff = l.diffForInterval( intervalPainterUnits );
2282 double c = 1 - lengthLeft / intervalPainterUnits;
2284 lengthLeft += l.length();
2287 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2291 lengthLeft -= intervalPainterUnits;
2294 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2299 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2303 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2310 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2313 while ( dest.size() < numberPointsRequired )
2314 dest << points.constLast();
2318void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver )
2320 if ( !points.isEmpty() )
2324 QPolygonF::const_iterator it = points.constBegin();
2326 for ( ++it; it != points.constEnd(); ++it )
2328 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2329 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2335 const double midPoint = length / 2;
2338 double thisSymbolAngle = 0;
2340 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2342 QVector< QPointF > angleStartPoints;
2343 QVector< QPointF > symbolPoints;
2344 QVector< QPointF > angleEndPoints;
2346 collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
2347 collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
2348 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
2350 pt = symbolPoints.at( 1 );
2351 MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2352 thisSymbolAngle = l.angle();
2357 it = points.constBegin();
2359 qreal last_at = 0, next_at = 0;
2361 for ( ++it; it != points.constEnd(); ++it )
2364 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2365 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2366 if ( next_at >= midPoint )
2373 MyLine l( last, next );
2374 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2375 pt = last + ( next - last ) * k;
2376 thisSymbolAngle = l.angle();
2428 if ( props.contains( QStringLiteral(
"interval" ) ) )
2429 interval = props[QStringLiteral(
"interval" )].toDouble();
2430 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2431 rotate = ( props[QStringLiteral(
"rotate" )].toString() == QLatin1String(
"1" ) );
2433 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2440 return QStringLiteral(
"MarkerLine" );
2457 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2460 mMarker->setRenderHints( hints );
2473 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >(
rotateSymbols(),
interval() );
2480 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2482 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
2483 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2484 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2485 element.appendChild( symbolizerElem );
2515 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2516 symbolizerElem.appendChild( strokeElem );
2519 QDomElement graphicStrokeElem = doc.createElement( QStringLiteral(
"se:GraphicStroke" ) );
2520 strokeElem.appendChild( graphicStrokeElem );
2525 markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
2529 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) ) );
2533 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"Missing marker line symbol layer. Skip it." ) ) );
2536 if ( !gap.isEmpty() )
2538 QDomElement gapElem = doc.createElement( QStringLiteral(
"se:Gap" ) );
2540 graphicStrokeElem.appendChild( gapElem );
2545 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
2548 symbolizerElem.appendChild( perpOffsetElem );
2557 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2558 if ( strokeElem.isNull() )
2561 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
2562 if ( graphicStrokeElem.isNull() )
2570 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2572 if ( it.key() == QLatin1String(
"placement" ) )
2574 if ( it.value() == QLatin1String(
"points" ) )
2576 else if ( it.value() == QLatin1String(
"firstPoint" ) )
2578 else if ( it.value() == QLatin1String(
"lastPoint" ) )
2580 else if ( it.value() == QLatin1String(
"centralPoint" ) )
2583 else if ( it.value() == QLatin1String(
"rotateMarker" ) )
2589 std::unique_ptr< QgsMarkerSymbol > marker;
2603 QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"Gap" ) );
2604 if ( !gapElem.isNull() )
2607 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
2613 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
2614 if ( !perpOffsetElem.isNull() )
2617 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2622 double scaleFactor = 1.0;
2623 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
2646 mMarker->setDataDefinedSize( property );
2653 const double prevOpacity =
mMarker->opacity();
2656 mMarker->setOpacity( prevOpacity );
2661 mMarker->setLineAngle( angle );
2679 mMarker->renderPoint( point, feature, context, layer, selected );
2691 return mMarker->size( context );
2697 mMarker->setOutputUnit( unit );
2714 attr.unite(
mMarker->usedAttributes( context ) );
2729 return (
mMarker->size( context ) / 2.0 ) +
2751 if ( props.contains( QStringLiteral(
"interval" ) ) )
2752 interval = props[QStringLiteral(
"interval" )].toDouble();
2753 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2754 rotate = ( props[QStringLiteral(
"rotate" )] == QLatin1String(
"1" ) );
2756 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2758 if ( props.contains( QStringLiteral(
"hash_angle" ) ) )
2760 x->setHashAngle( props[QStringLiteral(
"hash_angle" )].toDouble() );
2763 if ( props.contains( QStringLiteral(
"hash_length" ) ) )
2764 x->setHashLength( props[QStringLiteral(
"hash_length" )].toDouble() );
2766 if ( props.contains( QStringLiteral(
"hash_length_unit" ) ) )
2769 if ( props.contains( QStringLiteral(
"hash_length_map_unit_scale" ) ) )
2777 return QStringLiteral(
"HashLine" );
2783 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2786 mHashSymbol->setRenderHints( hints );
2799 map[ QStringLiteral(
"hash_angle" ) ] = QString::number( mHashAngle );
2801 map[QStringLiteral(
"hash_length" )] = QString::number( mHashLength );
2810 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >(
rotateSymbols(),
interval() );
2812 x->setHashAngle( mHashAngle );
2813 x->setHashLength( mHashLength );
2814 x->setHashLengthUnit( mHashLengthUnit );
2815 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2821 mHashSymbol->setColor(
color );
2827 return mHashSymbol ? mHashSymbol->color() :
mColor;
2832 return mHashSymbol.get();
2843 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2844 mColor = mHashSymbol->color();
2850 mHashLength =
width;
2865 return ( mHashSymbol->width( context ) / 2.0 )
2873 mHashSymbol->setOutputUnit( unit );
2880 attr.unite( mHashSymbol->usedAttributes( context ) );
2888 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
2897 mHashSymbol->setDataDefinedWidth( property );
2910 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
2915 mSymbolLineAngle = angle;
2920 return mSymbolAngle;
2925 mSymbolAngle = angle;
2930 double lineLength = mHashLength;
2936 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
2950 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
2955 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
2972 const double prevOpacity = mHashSymbol->opacity();
2973 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
2975 mHashSymbol->setOpacity( prevOpacity );
2994 QPolygonF offsetPoints;
2997 renderLine( points, context, patternThickness, patternLength, brush );
3006 renderLine( part, context, patternThickness, patternLength, brush );
3011void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3012 const double patternLength,
const QBrush &sourceBrush )
3018 QBrush brush = sourceBrush;
3023 QPolygonF inputPoints;
3024 inputPoints.reserve( points.size() );
3026 double minX = std::numeric_limits< double >::max();
3027 double minY = std::numeric_limits< double >::max();
3028 double maxX = std::numeric_limits< double >::lowest();
3029 double maxY = std::numeric_limits< double >::lowest();
3031 for (
const QPointF &pt : std::as_const( points ) )
3038 minX = std::min( minX, pt.x() );
3039 minY = std::min( minY, pt.y() );
3040 maxX = std::max( maxX, pt.x() );
3041 maxY = std::max( maxY, pt.y() );
3044 if ( inputPoints.size() < 2 )
3048 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3050 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3053 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3054 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3056 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3057 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3059 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3060 if ( temporaryImage.isNull() )
3069 temporaryImage.fill( Qt::transparent );
3092 QPainterPathStroker stroker;
3093 stroker.setWidth( lineThickness );
3094 stroker.setCapStyle( cap );
3095 stroker.setJoinStyle( join );
3098 path.addPolygon( inputPoints );
3099 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3102 QPainter imagePainter;
3103 imagePainter.begin( &temporaryImage );
3105 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3107 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3108 imagePainter.setPen( Qt::NoPen );
3110 QPointF segmentStartPoint = inputPoints.at( 0 );
3113 double progressThroughImage = 0;
3115 QgsPoint prevSegmentPolygonEndLeft;
3116 QgsPoint prevSegmentPolygonEndRight;
3122 for (
int i = 1; i < inputPoints.size(); ++i )
3127 const QPointF segmentEndPoint = inputPoints.at( i );
3129 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3132 QgsPoint thisSegmentPolygonEndLeft;
3133 QgsPoint thisSegmentPolygonEndRight;
3135 QgsPoint thisSegmentPolygonEndLeftForPainter;
3136 QgsPoint thisSegmentPolygonEndRightForPainter;
3144 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3146 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3147 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3151 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtils::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3152 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3155 const QgsPoint lastSegmentStartPointLeft =
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3156 const QgsPoint lastSegmentEndPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3157 const QgsPoint lastSegmentStartPointRight =
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3158 const QgsPoint lastSegmentEndPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3164 bool isIntersection =
false;
3166 if ( !isIntersection )
3167 prevSegmentPolygonEndLeft = startPointLeft;
3168 isIntersection =
false;
3169 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3170 if ( !isIntersection )
3171 prevSegmentPolygonEndRight = startPointRight;
3173 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3174 startLinePolygonRight = prevSegmentPolygonEndRight;
3178 prevSegmentPolygonEndLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3179 if ( cap != Qt::PenCapStyle::FlatCap )
3180 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3181 prevSegmentPolygonEndRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3182 if ( cap != Qt::PenCapStyle::FlatCap )
3183 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3187 if ( i < inputPoints.size() - 1 )
3192 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3194 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3195 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3200 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3203 const QgsPoint nextSegmentStartPointLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3204 const QgsPoint nextSegmentEndPointLeft =
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3205 const QgsPoint nextSegmentStartPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3206 const QgsPoint nextSegmentEndPointRight =
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3212 bool isIntersection =
false;
3214 if ( !isIntersection )
3215 thisSegmentPolygonEndLeft = endPointLeft;
3216 isIntersection =
false;
3217 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3218 if ( !isIntersection )
3219 thisSegmentPolygonEndRight = endPointRight;
3221 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3222 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3230 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3231 thisSegmentPolygonEndRight = startLinePolygonRight;
3233 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3234 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3238 thisSegmentPolygonEndLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3239 if ( cap != Qt::PenCapStyle::FlatCap )
3240 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3241 thisSegmentPolygonEndRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3242 if ( cap != Qt::PenCapStyle::FlatCap )
3243 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3245 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3246 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3252 QTransform brushTransform;
3253 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3254 brushTransform.rotate( -segmentAngleDegrees );
3255 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3259 brushTransform.translate( -( lineThickness / 2 ), 0 );
3261 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3263 brush.setTransform( brushTransform );
3264 imagePainter.setBrush( brush );
3267 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3268 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3269 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3270 << prevSegmentPolygonEndRight.
toQPointF()
3271 << prevSegmentPolygonEndLeft.
toQPointF() );
3274 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3275 imagePainter.setBrush( Qt::NoBrush );
3276 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3277 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3278 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3279 << prevSegmentPolygonEndRight.
toQPointF()
3280 << prevSegmentPolygonEndLeft.
toQPointF() );
3281 imagePainter.setPen( Qt::NoPen );
3286 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3287 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3288 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3289 progressThroughImage = fmod( progressThroughImage, patternLength );
3292 segmentStartPoint = segmentEndPoint;
3293 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3294 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3302 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3303 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3320 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique<QgsRasterLineSymbolLayer>();
3322 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3324 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3326 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3330 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3335 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
3336 res->setPath(
properties[QStringLiteral(
"imageFile" )].toString() );
3338 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3340 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3342 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3346 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3351 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3353 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3356 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
3358 res->setOpacity(
properties[QStringLiteral(
"alpha" )].toDouble() );
3361 return res.release();
3368 map[QStringLiteral(
"imageFile" )] =
mPath;
3370 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3377 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3381 map[QStringLiteral(
"alpha" )] = QString::number(
mOpacity );
3388 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3400 return res.release();
3405 const QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
3406 if ( it !=
properties.end() && it.value().type() == QVariant::String )
3422 return QStringLiteral(
"RasterLine" );
3432 bool cached =
false;
3434 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3435 static_cast< int >( std::ceil( scaledHeight ) ) ),
3460 double strokeWidth =
mWidth;
3477 bool cached =
false;
3479 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3480 static_cast< int >( std::ceil( scaledHeight ) ) ),
3485 if ( useSelectedColor )
3490 const QBrush brush( sourceImage );
3560 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique<QgsLineburstSymbolLayer>();
3562 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3564 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3566 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3570 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3575 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3577 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3579 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3583 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3588 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3590 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3593 if (
properties.contains( QStringLiteral(
"color_type" ) ) )
3596 if (
properties.contains( QStringLiteral(
"color" ) ) )
3600 if (
properties.contains( QStringLiteral(
"gradient_color2" ) ) )
3615 return res.release();
3622 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3629 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3635 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
3638#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
3650 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique< QgsLineburstSymbolLayer >();
3666 return res.release();
3671 return QStringLiteral(
"Lineburst" );
3687 double strokeWidth =
mWidth;
3703 if ( useSelectedColor )
3707 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3718 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3730 gradient.setColorAt( 0.0, color1 );
3731 gradient.setColorAt( 1.0,
color2 );
3733 const QBrush brush( gradient );
MarkerLinePlacement
Defines how/where the symbols should be placed on a line.
@ CurvePoint
Place symbols at every virtual curve point in the line (used when rendering curved geometry types onl...
@ InnerVertices
Inner vertices (i.e. all vertices except the first and last vertex) (since QGIS 3....
@ LastVertex
Place symbols on the last vertex in the line.
@ CentralPoint
Place symbols at the mid point of the line.
@ SegmentCenter
Place symbols at the center of every line segment.
@ Vertex
Place symbols on every vertex in the line.
@ Interval
Place symbols at regular intervals.
@ FirstVertex
Place symbols on the first vertex in the line.
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
GradientColorSource
Gradient color sources.
@ ColorRamp
Gradient color ramp.
@ Curve
An intermediate point on a segment defining the curvature of the segment.
@ Segment
The actual start or end point of a segment.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes)
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
@ RenderingSubSymbol
Set whenever a sub-symbol of a parent symbol is currently being rendered. Can be used during symbol a...
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
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 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.
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.
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.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
void addStopsToGradient(QGradient *gradient, double opacity=1) const
Copy color ramp stops to a QGradient.
Line symbol layer type which draws repeating line sections along a line feature.
double hashAngle() const
Returns the angle to use when drawing the hashed lines sections, in degrees clockwise.
QgsHashedLineSymbolLayer(bool rotateSymbol=true, double interval=3)
Constructor for QgsHashedLineSymbolLayer.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setWidth(double width) override
Sets the width of the line symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
double width() const override
Returns the estimated width for the line symbol layer.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsHashedLineSymbolLayer, using the settings serialized in the properties map (correspo...
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsHashedLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
~QgsHashedLineSymbolLayer() override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QColor color() const override
Returns the "representative" color of the symbol layer.
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString layerType() const override
Returns a string that represents this layer type.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setHashAngle(double angle)
Sets the angle to use when drawing the hashed lines sections, in degrees clockwise.
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
static void overlayColor(QImage &image, const QColor &color)
Overlays a color onto an image.
Qgis::RenderUnit mOffsetUnit
RenderRingFilter
Options for filtering rings when the line symbol layer is being used to render a polygon's rings.
@ ExteriorRingOnly
Render the exterior ring only.
@ InteriorRingsOnly
Render the interior rings only.
@ AllRings
Render both exterior and interior rings.
QgsMapUnitScale mWidthMapUnitScale
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void setWidthMapUnitScale(const QgsMapUnitScale &scale)
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit mWidthUnit
void setOffset(double offset)
Sets the line's offset.
RenderRingFilter mRingFilter
void setOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the line's offset.
void setWidthUnit(Qgis::RenderUnit unit)
Sets the units for the line's width.
virtual double width() const
Returns the estimated width for the line symbol layer.
QgsMapUnitScale mOffsetMapUnitScale
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the line's offset.
QgsMapUnitScale mapUnitScale() const override
void setRingFilter(QgsLineSymbolLayer::RenderRingFilter filter)
Sets the line symbol layer's ring filter, which controls which rings are rendered when the line symbo...
void setMapUnitScale(const QgsMapUnitScale &scale) override
double offset() const
Returns the line's offset.
Qgis::RenderUnit offsetUnit() const
Returns the units for the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
Line symbol layer type which draws a gradient pattern perpendicularly along a line.
std::unique_ptr< QgsColorRamp > mGradientRamp
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp used for the gradient line.
QColor color2() const
Returns the color for endpoint of gradient, only used if the gradient color type is set to SimpleTwoC...
Qgis::GradientColorSource mGradientColorType
QString layerType() const override
Returns a string that represents this layer type.
~QgsLineburstSymbolLayer() override
QgsLineburstSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsMapUnitScale mapUnitScale() const override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsLineburstSymbolLayer, using the settings serialized in the properties map (correspon...
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QgsLineburstSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, const QColor &color2=Qt::white)
Constructor for QgsLineburstSymbolLayer, with the specified start and end gradient colors.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsColorRamp * colorRamp()
Returns the color ramp used for the gradient line.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
void transformInPlace(double &x, double &y) const
Transforms device coordinates to map coordinates.
Struct for storing maximum and minimum scales for measurements in map units.
Line symbol layer type which draws repeating marker symbols along a line feature.
Q_DECL_DEPRECATED bool rotateMarker() const
Shall the marker be rotated.
std::unique_ptr< QgsMarkerSymbol > mMarker
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsMarkerLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
double width() const override
Returns the estimated width for the line symbol layer.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsMarkerLineSymbolLayer, using the settings serialized in the properties map (correspo...
QgsMarkerLineSymbolLayer(bool rotateMarker=DEFAULT_MARKERLINE_ROTATE, double interval=DEFAULT_MARKERLINE_INTERVAL)
Constructor for QgsMarkerLineSymbolLayer.
void setWidth(double width) override
Sets the width of the line symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
~QgsMarkerLineSymbolLayer() override
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QString layerType() const override
Returns a string that represents this layer type.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsMarkerLineSymbolLayer from an SLD XML DOM element.
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
Abstract base class for marker symbol layers.
A marker symbol type, for rendering Point and MultiPoint geometries.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Resolves relative paths into absolute paths and vice versa.
A class to represent a 2D point.
QgsPointXY project(double distance, double bearing) const
Returns a new point which corresponds to this point projected by a specified distance in a specified ...
Point geometry type, with support for z-dimension and m-values.
QPointF toQPointF() const
Returns the point as a QPointF.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const override
Returns the calculated value of the property with the specified key from within the collection.
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
A store for object properties.
Line symbol layer type which draws line sections using a raster image file.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QgsRasterLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
double opacity() const
Returns the line opacity.
QString path() const
Returns the raster image path.
void setPath(const QString &path)
Set the raster image path.
QString layerType() const override
Returns a string that represents this layer type.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
QgsRasterLineSymbolLayer(const QString &path=QString())
Constructor for QgsRasterLineSymbolLayer, with the specified raster image path.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsRasterLineSymbolLayer, using the settings serialized in the properties map (correspo...
QColor color() const override
Returns the "representative" color of the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsMapUnitScale mapUnitScale() const override
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
virtual ~QgsRasterLineSymbolLayer()
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
const QgsVectorSimplifyMethod & vectorSimplifyMethod() const
Returns the simplification settings to use when rendering vector layers.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QColor selectionColor() const
Returns the color to use when rendering selected features.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
const QgsAbstractGeometry * geometry() const
Returns pointer to the unsegmentized geometry.
Scoped object for saving and restoring a QPainter object's state.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void setDrawInsidePolygon(bool drawInsidePolygon)
Sets whether the line should only be drawn inside polygons, and any portion of the line which falls o...
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QgsMapUnitScale mapUnitScale() const override
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QVector< qreal > customDashVector() const
Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the outline of polygon, using the given render context.
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
void setCustomDashPatternMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for lengths used in the custom dash pattern.
void setTrimDistanceEndMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the end of the line.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void setTrimDistanceEnd(double distance)
Sets the trim distance for the end of the line, which dictates a length from the end of the line at w...
double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets offset.
QgsSimpleLineSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, double width=DEFAULT_SIMPLELINE_WIDTH, Qt::PenStyle penStyle=DEFAULT_SIMPLELINE_PENSTYLE)
Constructor for QgsSimpleLineSymbolLayer.
~QgsSimpleLineSymbolLayer() override
void setUseCustomDashPattern(bool b)
Sets whether the line uses a custom dash pattern.
void setTweakDashPatternOnCorners(bool enabled)
Sets whether dash patterns tweaks should be applied on sharp corners, to ensure that a double-length ...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
void setCustomDashVector(const QVector< qreal > &vector)
Sets the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ren...
void setDashPatternOffset(double offset)
Sets the dash pattern offset, which dictates how far along the dash pattern the pattern should start ...
QColor dxfColor(QgsSymbolRenderContext &context) const override
Gets color.
QString layerType() const override
Returns a string that represents this layer type.
void setDashPatternOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the dash pattern offset.
QgsSimpleLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
void setAlignDashPattern(bool enabled)
Sets whether dash patterns should be aligned to the start and end of lines, by applying subtle tweaks...
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleLineSymbolLayer from an SLD XML DOM element.
double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets line width.
void setTrimDistanceStartMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the start of the line.
QVector< qreal > dxfCustomDashPattern(Qgis::RenderUnit &unit) const override
Gets dash pattern.
Qt::PenCapStyle penCapStyle() const
Returns the pen cap style used to render the line (e.g.
void setTrimDistanceEndUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the end of the line.
void setDashPatternOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the dash pattern offset.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setTrimDistanceStart(double distance)
Sets the trim distance for the start of the line, which dictates a length from the start of the line ...
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setTrimDistanceStartUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the start of the line.
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
void setCustomDashPatternUnit(Qgis::RenderUnit unit)
Sets the unit for lengths used in the custom dash pattern.
static QString encodePenStyle(Qt::PenStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static QColor decodeColor(const QString &str)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static QString encodeColor(const QColor &color)
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
static Qt::PenStyle decodePenStyle(const QString &str)
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static QString encodeRealVector(const QVector< qreal > &v)
Property
Data definable properties.
@ PropertyStrokeStyle
Stroke style (eg solid, dashed)
@ PropertyPlacement
Line marker placement.
@ PropertyFile
Filename, eg for svg files.
@ PropertyCapStyle
Line cap style.
@ PropertyLineDistance
Distance between lines, or length of lines for hash line symbols.
@ PropertyOffsetAlongLine
Offset along line.
@ PropertyCustomDash
Custom dash pattern.
@ PropertyJoinStyle
Line join style.
@ PropertyTrimEnd
Trim distance from end of line (since QGIS 3.20)
@ PropertyOpacity
Opacity.
@ PropertySecondaryColor
Secondary color (eg for gradient fills)
@ PropertyLineAngle
Line angle, or angle of hash lines for hash line symbols.
@ PropertyTrimStart
Trim distance from start of line (since QGIS 3.20)
@ PropertyOffset
Symbol offset.
@ PropertyStrokeWidth
Stroke width.
@ PropertyDashPatternOffset
Dash pattern offset,.
@ PropertyAverageAngleLength
Length to average symbol angles over.
@ PropertyInterval
Line marker interval.
@ PropertyStrokeColor
Stroke color.
@ PropertyWidth
Symbol width.
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.
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.
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
const QgsFeature * feature() const
Returns the current feature being rendered.
Qgis::GeometryType originalGeometryType() const
Returns the geometry type for the original feature geometry being rendered.
QgsFields fields() const
Fields of the layer.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
qreal opacity() const
Returns the opacity for the symbol.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for all rendered symbols.
qreal opacity() const
Returns the opacity for the symbol.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
Base class for templated line symbols, e.g.
bool rotateSymbols() const
Returns true if the repeating symbols be rotated to match their line segment orientation.
Qgis::RenderUnit outputUnit() const FINAL
Returns the units to use for sizes and widths within the symbol layer.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
static void setCommonProperties(QgsTemplatedLineSymbolLayerBase *destLayer, const QVariantMap &properties)
Sets all common symbol properties in the destLayer, using the settings serialized in the properties m...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
QgsMapUnitScale mapUnitScale() const FINAL
void setMapUnitScale(const QgsMapUnitScale &scale) FINAL
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setIntervalUnit(Qgis::RenderUnit unit)
Sets the units for the interval between symbols.
void setAverageAngleUnit(Qgis::RenderUnit unit)
Sets the unit for the length over which the line's direction is averaged when calculating individual ...
double interval() const
Returns the interval between individual symbols.
void setOffsetAlongLineUnit(Qgis::RenderUnit unit)
Sets the unit used for calculating the offset along line for symbols.
void setAverageAngleMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the length over which the line's direction is averaged when calculating i...
const QgsMapUnitScale & intervalMapUnitScale() const
Returns the map unit scale for the interval between symbols.
double offsetAlongLine() const
Returns the offset along the line for the symbol placement.
~QgsTemplatedLineSymbolLayerBase() override
void copyTemplateSymbolProperties(QgsTemplatedLineSymbolLayerBase *destLayer) const
Copies all common properties of this layer to another templated symbol layer.
Qgis::MarkerLinePlacements placements() const
Returns the placement of the symbols.
void setOffsetAlongLine(double offsetAlongLine)
Sets the the offset along the line for the symbol placement.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) FINAL
Renders the line symbol layer along the outline of polygon, using the given render context.
Qgis::RenderUnit offsetAlongLineUnit() const
Returns the unit used for calculating the offset along line for symbols.
QgsTemplatedLineSymbolLayerBase(bool rotateSymbol=true, double interval=3)
Constructor for QgsTemplatedLineSymbolLayerBase.
virtual void setSymbolLineAngle(double angle)=0
Sets the line angle modification for the symbol's angle.
void setInterval(double interval)
Sets the interval between individual symbols.
Qgis::RenderUnit intervalUnit() const
Returns the units for the interval between symbols.
Q_DECL_DEPRECATED Qgis::MarkerLinePlacement placement() const
Returns the placement of the symbols.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void setPlaceOnEveryPart(bool respect)
Sets whether the placement applies for every part of multi-part feature geometries.
void setPlacements(Qgis::MarkerLinePlacements placements)
Sets the placement of the symbols.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit averageAngleUnit() const
Returns the unit for the length over which the line's direction is averaged when calculating individu...
Q_DECL_DEPRECATED void setPlacement(Qgis::MarkerLinePlacement placement)
Sets the placement of the symbols.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
const QgsMapUnitScale & offsetAlongLineMapUnitScale() const
Returns the map unit scale used for calculating the offset in map units along line for symbols.
virtual void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false)=0
Renders the templated symbol at the specified point, using the given render context.
void setIntervalMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the interval between symbols.
void setOffsetAlongLineMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale used for calculating the offset in map units along line for symbols.
void setAverageAngleLength(double length)
Sets the length of line over which the line's direction is averaged when calculating individual symbo...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QMap< QString, QString > QgsStringMap
#define DEFAULT_MARKERLINE_INTERVAL
#define DEFAULT_SIMPLELINE_WIDTH
#define DEFAULT_MARKERLINE_ROTATE
#define DEFAULT_SIMPLELINE_PENSTYLE
#define DEFAULT_SIMPLELINE_COLOR
#define QgsDebugMsgLevel(str, level)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
Single variable definition for use within a QgsExpressionContextScope.
Utility class for identifying a unique vertex within a geometry.
Qgis::VertexType type
Vertex type.