37#include <QDomDocument>
43 : mPenStyle( penStyle )
47 mCustomDashVector << 5 << 2;
57 mCustomDashPatternUnit = unit;
58 mDashPatternOffsetUnit = unit;
59 mTrimDistanceStartUnit = unit;
60 mTrimDistanceEndUnit = unit;
68 return Qgis::RenderUnit::Unknown;
75 return mWidthUnit == Qgis::RenderUnit::MapUnits ||
mWidthUnit == Qgis::RenderUnit::MetersInMapUnits
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;
396 if ( mTrimDistanceStartUnit == Qgis::RenderUnit::Percentage )
399 startTrim = startTrim * 0.01 * totalLength;
405 if ( mTrimDistanceEndUnit == Qgis::RenderUnit::Percentage )
407 if ( totalLength < 0 )
409 endTrim = endTrim * 0.01 * totalLength;
422 mPen.setColor( penColor );
425 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
427 const QPen pen = context.
selected() ? mSelPen : mPen;
429 if ( !pen.dashPattern().isEmpty() )
432 const QVector<double> pattern = pen.dashPattern();
433 bool foundNonNull =
false;
434 for (
int i = 0; i < pattern.size(); ++i )
446 p->setBrush( Qt::NoBrush );
449 std::unique_ptr< QgsScopedQPainterState > painterState;
450 if ( points.size() <= 2 &&
453 ( p->renderHints() & QPainter::Antialiasing ) )
455 painterState = std::make_unique< QgsScopedQPainterState >( p );
456 p->setRenderHint( QPainter::Antialiasing,
false );
459 const bool applyPatternTweaks = mAlignDashPattern
460 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
461 && pen.dashOffset() == 0;
465 if ( applyPatternTweaks )
467 drawPathWithDashPatternTweaks( p, points, pen );
473 path.addPolygon( points );
488 for (
const QPolygonF &part : mline )
490 if ( applyPatternTweaks )
492 drawPathWithDashPatternTweaks( p, part, pen );
498 path.addPolygon( part );
509 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
515 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
518 map[QStringLiteral(
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
522 map[QStringLiteral(
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
525 map[QStringLiteral(
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
528 map[QStringLiteral(
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
531 map[QStringLiteral(
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
532 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
533 map[QStringLiteral(
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
534 map[QStringLiteral(
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
573 if ( mPenStyle == Qt::NoPen )
576 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
577 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
578 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
579 element.appendChild( symbolizerElem );
585 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
586 symbolizerElem.appendChild( strokeElem );
588 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
597 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
600 symbolizerElem.appendChild( perpOffsetElem );
606 if ( mUseCustomDashPattern )
609 mPen.color(), mPenJoinStyle,
610 mPenCapStyle,
mOffset, &mCustomDashVector );
623 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
624 if ( strokeElem.isNull() )
641 QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
642 if ( !perpOffsetElem.isNull() )
645 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
650 double scaleFactor = 1.0;
651 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
666void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
672 bool hasStrokeWidthExpression =
false;
679 pen.setWidthF( scaledWidth );
680 selPen.setWidthF( scaledWidth );
681 hasStrokeWidthExpression =
true;
690 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
691 pen.setColor( penColor );
705 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
709 QVector<qreal> dashVector;
713 QStringList dashList = exprVal.toString().split(
';' );
714 QStringList::const_iterator dashIt = dashList.constBegin();
715 for ( ; dashIt != dashList.constEnd(); ++dashIt )
719 pen.setDashPattern( dashVector );
726 QVector<qreal> scaledVector;
727 for (
double v : std::as_const( mCustomDashVector ) )
732 mPen.setDashPattern( scaledVector );
736 double patternOffset = mDashPatternOffset;
772void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
774 if ( pen.dashPattern().empty() || points.size() < 2 )
777 QVector< qreal > sourcePattern = pen.dashPattern();
778 const double dashWidthDiv = std::max( 1.0001, pen.widthF() );
780 for (
int i = 0; i < sourcePattern.size(); ++ i )
781 sourcePattern[i] *= pen.widthF();
783 if ( pen.widthF() <= 1.0 )
784 pen.setWidthF( 1.0001 );
786 QVector< qreal > buffer;
787 QPolygonF bufferedPoints;
788 QPolygonF previousSegmentBuffer;
793 auto ptIt = points.constBegin();
794 double totalBufferLength = 0;
795 int patternIndex = 0;
796 double currentRemainingDashLength = 0;
797 double currentRemainingGapLength = 0;
799 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
801 QVector< qreal > result;
802 result.reserve( buffer.size() );
803 for (
auto it = buffer.begin(); it != buffer.end(); )
807 while ( dash == 0 && !result.empty() )
809 result.last() += gap;
811 if ( it == buffer.end() )
816 while ( gap == 0 && it != buffer.end() )
821 result << dash << gap;
826 double currentBufferLineLength = 0;
827 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
828 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
830 if ( buffer.empty() || bufferedPoints.size() < 2 )
835 if ( currentRemainingDashLength )
838 buffer << currentRemainingDashLength << 0.0;
839 totalBufferLength += currentRemainingDashLength;
841 QVector< qreal > compressed = compressPattern( buffer );
842 if ( !currentRemainingDashLength )
845 totalBufferLength -= compressed.last();
846 compressed.last() = 0;
850 const double scaleFactor = currentBufferLineLength / totalBufferLength;
852 bool shouldFlushPreviousSegmentBuffer =
false;
854 if ( !previousSegmentBuffer.empty() )
858 if ( !firstDashSubstring.empty() )
864 compressed = compressed.mid( 2 );
865 shouldFlushPreviousSegmentBuffer = !compressed.empty();
868 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
870 QPen adjustedPen = pen;
871 adjustedPen.setStyle( Qt::SolidLine );
872 painter->setPen( adjustedPen );
874 path.addPolygon( previousSegmentBuffer );
875 painter->drawPath( path );
876 previousSegmentBuffer.clear();
879 double finalDash = 0;
886 if ( !compressed.empty() )
888 finalDash = compressed.at( compressed.size() - 2 );
889 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
891 const QPolygonF thisPoints = bufferedPoints;
897 previousSegmentBuffer << bufferedPoints;
901 currentBufferLineLength = 0;
902 currentRemainingDashLength = 0;
903 currentRemainingGapLength = 0;
904 totalBufferLength = 0;
907 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
909 QPen adjustedPen = pen;
910 if ( !compressed.empty() )
913 compressed = compressed.mid( 0, 32 );
914 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
915 adjustedPen.setDashPattern( compressed );
919 adjustedPen.setStyle( Qt::SolidLine );
922 painter->setPen( adjustedPen );
924 path.addPolygon( bufferedPoints );
925 painter->drawPath( path );
928 bufferedPoints.clear();
934 bufferedPoints << p2;
935 for ( ; ptIt != points.constEnd(); ++ptIt )
943 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
944 currentBufferLineLength += remainingSegmentDistance;
948 if ( currentRemainingDashLength > 0 )
951 if ( remainingSegmentDistance >= currentRemainingDashLength )
954 buffer << currentRemainingDashLength << 0.0;
955 totalBufferLength += currentRemainingDashLength;
956 remainingSegmentDistance -= currentRemainingDashLength;
958 currentRemainingDashLength = 0.0;
959 currentRemainingGapLength = sourcePattern.at( patternIndex );
964 buffer << remainingSegmentDistance << 0.0;
965 totalBufferLength += remainingSegmentDistance;
966 currentRemainingDashLength -= remainingSegmentDistance;
970 if ( currentRemainingGapLength > 0 )
973 if ( remainingSegmentDistance >= currentRemainingGapLength )
976 buffer << 0.0 << currentRemainingGapLength;
977 totalBufferLength += currentRemainingGapLength;
978 remainingSegmentDistance -= currentRemainingGapLength;
979 currentRemainingGapLength = 0.0;
985 buffer << 0.0 << remainingSegmentDistance;
986 totalBufferLength += remainingSegmentDistance;
987 currentRemainingGapLength -= remainingSegmentDistance;
992 if ( patternIndex >= sourcePattern.size() )
995 const double nextPatternDashLength = sourcePattern.at( patternIndex );
996 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
997 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
999 buffer << nextPatternDashLength << nextPatternGapLength;
1000 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1001 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1004 else if ( nextPatternDashLength <= remainingSegmentDistance )
1007 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1008 totalBufferLength += remainingSegmentDistance;
1009 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1010 currentRemainingDashLength = 0;
1017 buffer << remainingSegmentDistance << 0.0;
1018 totalBufferLength += remainingSegmentDistance;
1019 currentRemainingGapLength = 0;
1020 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1025 bufferedPoints << p1;
1026 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1028 QPointF nextPoint = *( ptIt + 1 );
1034 flushBuffer( &nextPoint );
1035 bufferedPoints << p1;
1038 if ( patternIndex % 2 == 1 )
1042 currentRemainingDashLength = sourcePattern.at( patternIndex );
1049 flushBuffer(
nullptr );
1050 if ( !previousSegmentBuffer.empty() )
1052 QPen adjustedPen = pen;
1053 adjustedPen.setStyle( Qt::SolidLine );
1054 painter->setPen( adjustedPen );
1056 path.addPolygon( previousSegmentBuffer );
1057 painter->drawPath( path );
1058 previousSegmentBuffer.clear();
1064 if ( mDrawInsidePolygon )
1078 unit = mCustomDashPatternUnit;
1079 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1097 if (
mWidthUnit == Qgis::RenderUnit::MapUnits )
1116 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1121 return mAlignDashPattern;
1131 return mPatternCartographicTweakOnSharpCorners;
1136 mPatternCartographicTweakOnSharpCorners =
enabled;
1164 MyLine( QPointF p1, QPointF p2 )
1165 : mVertical( false )
1166 , mIncreasing( false )
1178 mIncreasing = ( p2.y() > p1.y() );
1183 mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
1184 mIncreasing = ( p2.x() > p1.x() );
1188 double x = ( p2.x() - p1.x() );
1189 double y = ( p2.y() - p1.y() );
1190 mLength = std::sqrt( x * x + y * y );
1196 double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
1204 QPointF diffForInterval(
double interval )
1207 return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
1209 double alpha = std::atan( mT );
1210 double dx = std::cos( alpha ) * interval;
1211 double dy = std::sin( alpha ) * interval;
1212 return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
1215 double length()
const {
return mLength; }
1230 : mRotateSymbols( rotateSymbol )
1231 , mInterval( interval )
1269 if ( mRenderingFeature )
1273 mFeatureSymbolOpacity = context.
opacity();
1274 mCurrentFeatureIsSelected = context.
selected();
1292 QString placementString = exprVal.toString();
1293 if ( placementString.compare( QLatin1String(
"interval" ), Qt::CaseInsensitive ) == 0 )
1297 else if ( placementString.compare( QLatin1String(
"vertex" ), Qt::CaseInsensitive ) == 0 )
1301 else if ( placementString.compare( QLatin1String(
"innervertices" ), Qt::CaseInsensitive ) == 0 )
1305 else if ( placementString.compare( QLatin1String(
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
1309 else if ( placementString.compare( QLatin1String(
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
1313 else if ( placementString.compare( QLatin1String(
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
1317 else if ( placementString.compare( QLatin1String(
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
1321 else if ( placementString.compare( QLatin1String(
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
1334 double averageOver = mAverageAngleLength;
1345 renderPolylineInterval( points, context, averageOver );
1347 renderPolylineCentral( points, context, averageOver );
1351 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1354 mHasRenderedFirstPart = mRenderingFeature;
1370 for (
int part = 0; part < mline.count(); ++part )
1372 const QPolygonF &points2 = mline[ part ];
1375 renderPolylineInterval( points2, context, averageOver );
1377 renderPolylineCentral( points2, context, averageOver );
1385 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1388 mHasRenderedFirstPart = mRenderingFeature;
1408 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1438 for (
int i = 0; i < rings->size(); ++i )
1463 return Qgis::RenderUnit::Unknown;
1471 mIntervalUnit = unit;
1472 mOffsetAlongLineUnit = unit;
1473 mAverageAngleLengthUnit = unit;
1498 map[QStringLiteral(
"rotate" )] = (
rotateSymbols() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1499 map[QStringLiteral(
"interval" )] = QString::number(
interval() );
1500 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
1501 map[QStringLiteral(
"offset_along_line" )] = QString::number(
offsetAlongLine() );
1508 map[QStringLiteral(
"average_angle_length" )] = QString::number( mAverageAngleLength );
1514 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
1515 map[QStringLiteral(
"place_on_every_part" )] = mPlaceOnEveryPart;
1521 return mPlaceOnEveryPart
1529 mRenderingFeature =
true;
1530 mHasRenderedFirstPart =
false;
1535 mRenderingFeature =
false;
1543 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1544 mFeatureSymbolOpacity = 1;
1571 if (
properties.contains( QStringLiteral(
"offset" ) ) )
1575 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
1579 if (
properties.contains( QStringLiteral(
"interval_unit" ) ) )
1583 if (
properties.contains( QStringLiteral(
"offset_along_line" ) ) )
1587 if (
properties.contains( QStringLiteral(
"offset_along_line_unit" ) ) )
1591 if (
properties.contains( ( QStringLiteral(
"offset_along_line_map_unit_scale" ) ) ) )
1596 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1600 if (
properties.contains( QStringLiteral(
"interval_map_unit_scale" ) ) )
1605 if (
properties.contains( QStringLiteral(
"average_angle_length" ) ) )
1609 if (
properties.contains( QStringLiteral(
"average_angle_unit" ) ) )
1613 if (
properties.contains( ( QStringLiteral(
"average_angle_map_unit_scale" ) ) ) )
1618 if (
properties.contains( QStringLiteral(
"placement" ) ) )
1620 if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"vertex" ) )
1622 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"lastvertex" ) )
1624 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"firstvertex" ) )
1626 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"centralpoint" ) )
1628 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"curvepoint" ) )
1630 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"segmentcenter" ) )
1635 else if (
properties.contains( QStringLiteral(
"placements" ) ) )
1641 if (
properties.contains( QStringLiteral(
"ring_filter" ) ) )
1651void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver )
1653 if ( points.isEmpty() )
1656 double lengthLeft = 0;
1688 if ( painterUnitInterval < 0 )
1691 double painterUnitOffsetAlongLine = 0;
1694 double totalLength = -1;
1700 case Qgis::RenderUnit::Millimeters:
1701 case Qgis::RenderUnit::MapUnits:
1702 case Qgis::RenderUnit::Pixels:
1703 case Qgis::RenderUnit::Points:
1704 case Qgis::RenderUnit::Inches:
1705 case Qgis::RenderUnit::Unknown:
1706 case Qgis::RenderUnit::MetersInMapUnits:
1709 case Qgis::RenderUnit::Percentage:
1715 if ( points.isClosed() )
1717 if ( painterUnitOffsetAlongLine > 0 )
1719 if ( totalLength < 0 )
1721 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1723 else if ( painterUnitOffsetAlongLine < 0 )
1725 if ( totalLength < 0 )
1727 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1739 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1741 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1743 QVector< QPointF > angleStartPoints;
1744 QVector< QPointF > symbolPoints;
1745 QVector< QPointF > angleEndPoints;
1753 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
1755 if ( symbolPoints.empty() )
1761 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1764 symbolPoints.pop_back();
1767 angleEndPoints.reserve( symbolPoints.size() );
1768 angleStartPoints.reserve( symbolPoints.size() );
1769 if ( averageOver <= painterUnitOffsetAlongLine )
1771 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
1775 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1777 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
1780 for (
int i = 0; i < symbolPoints.size(); ++ i )
1785 const QPointF pt = symbolPoints[i];
1786 const QPointF startPt = angleStartPoints[i];
1787 const QPointF endPt = angleEndPoints[i];
1789 MyLine l( startPt, endPt );
1804 QPointF lastPt = points[0];
1805 for (
int i = 1; i < points.count(); ++i )
1810 const QPointF &pt = points[i];
1816 MyLine l( lastPt, pt );
1817 QPointF diff = l.diffForInterval( painterUnitInterval );
1821 double c = 1 - lengthLeft / painterUnitInterval;
1823 lengthLeft += l.length();
1832 while ( lengthLeft > painterUnitInterval )
1836 lengthLeft -= painterUnitInterval;
1848static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1851 double a1 = MyLine( prevPt, pt ).angle();
1852 double a2 = MyLine( pt, nextPt ).angle();
1853 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1855 return std::atan2( unitY, unitX );
1860 if ( points.isEmpty() )
1865 int i = -1, maxCount = 0;
1866 bool isRing =
false;
1880 double totalLength = -1;
1886 case Qgis::RenderUnit::Millimeters:
1887 case Qgis::RenderUnit::MapUnits:
1888 case Qgis::RenderUnit::Pixels:
1889 case Qgis::RenderUnit::Points:
1890 case Qgis::RenderUnit::Inches:
1891 case Qgis::RenderUnit::Unknown:
1892 case Qgis::RenderUnit::MetersInMapUnits:
1895 case Qgis::RenderUnit::Percentage:
1900 if ( points.isClosed() )
1904 if ( totalLength < 0 )
1910 if ( totalLength < 0 )
1983 i = points.count() - 1;
1985 maxCount = points.count();
1993 maxCount = points.count() - 1;
2001 maxCount = points.count();
2002 if ( points.first() == points.last() )
2019 renderOffsetVertexAlongLine( points, i, distance, context,
placement );
2026 prevPoint = points.at( 0 );
2028 QPointF symbolPoint;
2029 for ( ; i < maxCount; ++i )
2040 QPointF currentPoint = points.at( i );
2041 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2042 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2045 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2046 currentPoint.x() - prevPoint.x() );
2049 prevPoint = currentPoint;
2053 symbolPoint = points.at( i );
2057 double angle = markerAngle( points, isRing, i );
2062 mFinalVertex = symbolPoint;
2068double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2071 const QPointF &pt = points[vertex];
2073 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2075 int prevIndex = vertex - 1;
2076 int nextIndex = vertex + 1;
2078 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2080 prevIndex = points.count() - 2;
2084 QPointF prevPoint, nextPoint;
2085 while ( prevIndex >= 0 )
2087 prevPoint = points[ prevIndex ];
2088 if ( prevPoint != pt )
2095 while ( nextIndex < points.count() )
2097 nextPoint = points[ nextIndex ];
2098 if ( nextPoint != pt )
2105 if ( prevIndex >= 0 && nextIndex < points.count() )
2107 angle = _averageAngle( prevPoint, pt, nextPoint );
2114 while ( vertex < points.size() - 1 )
2116 const QPointF &nextPt = points[vertex + 1];
2119 angle = MyLine( pt, nextPt ).angle();
2128 while ( vertex >= 1 )
2130 const QPointF &prevPt = points[vertex - 1];
2133 angle = MyLine( prevPt, pt ).angle();
2145 if ( points.isEmpty() )
2154 bool isRing =
false;
2155 if ( points.first() == points.last() )
2157 double angle = markerAngle( points, isRing, vertex );
2160 mFinalVertex = points[vertex];
2166 int pointIncrement = distance > 0 ? 1 : -1;
2167 QPointF previousPoint = points[vertex];
2168 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2169 int endPoint = distance > 0 ? points.count() - 1 : 0;
2170 double distanceLeft = std::fabs( distance );
2172 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2174 const QPointF &pt = points[i];
2176 if ( previousPoint == pt )
2180 MyLine l( previousPoint, pt );
2182 if ( distanceLeft < l.length() )
2185 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2191 mFinalVertex = markerPoint;
2197 distanceLeft -= l.length();
2204void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
double initialLag,
int numberPointsRequired )
2209 QVector< QPointF > points = p;
2210 const bool closedRing = points.first() == points.last();
2212 double lengthLeft = initialOffset;
2214 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2215 if ( initialLagLeft < 0 && closedRing )
2218 QPointF lastPt = points.constLast();
2219 QVector< QPointF > pseudoPoints;
2220 for (
int i = points.count() - 2; i > 0; --i )
2222 if ( initialLagLeft >= 0 )
2227 const QPointF &pt = points[i];
2232 MyLine l( lastPt, pt );
2233 initialLagLeft += l.length();
2238 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2240 points = pseudoPoints;
2245 while ( initialLagLeft < 0 )
2247 dest << points.constFirst();
2248 initialLagLeft += intervalPainterUnits;
2251 if ( initialLag > 0 )
2253 lengthLeft += intervalPainterUnits - initialLagLeft;
2256 QPointF lastPt = points[0];
2257 for (
int i = 1; i < points.count(); ++i )
2259 const QPointF &pt = points[i];
2263 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2272 MyLine l( lastPt, pt );
2273 QPointF diff = l.diffForInterval( intervalPainterUnits );
2277 double c = 1 - lengthLeft / intervalPainterUnits;
2279 lengthLeft += l.length();
2282 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2286 lengthLeft -= intervalPainterUnits;
2289 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2294 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2298 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2305 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2308 while ( dest.size() < numberPointsRequired )
2309 dest << points.constLast();
2313void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver )
2315 if ( !points.isEmpty() )
2319 QPolygonF::const_iterator it = points.constBegin();
2321 for ( ++it; it != points.constEnd(); ++it )
2323 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2324 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2330 const double midPoint = length / 2;
2333 double thisSymbolAngle = 0;
2335 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2337 QVector< QPointF > angleStartPoints;
2338 QVector< QPointF > symbolPoints;
2339 QVector< QPointF > angleEndPoints;
2341 collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
2342 collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
2343 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
2345 pt = symbolPoints.at( 1 );
2346 MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2347 thisSymbolAngle = l.angle();
2352 it = points.constBegin();
2354 qreal last_at = 0, next_at = 0;
2357 for ( ++it; it != points.constEnd(); ++it )
2360 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2361 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2362 if ( next_at >= midPoint )
2370 MyLine l( last, next );
2371 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2372 pt = last + ( next - last ) * k;
2373 thisSymbolAngle = l.angle();
2425 if ( props.contains( QStringLiteral(
"interval" ) ) )
2426 interval = props[QStringLiteral(
"interval" )].toDouble();
2427 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2428 rotate = ( props[QStringLiteral(
"rotate" )].toString() == QLatin1String(
"1" ) );
2430 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2437 return QStringLiteral(
"MarkerLine" );
2454 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2457 mMarker->setRenderHints( hints );
2470 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >(
rotateSymbols(),
interval() );
2477 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2479 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
2480 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2481 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2482 element.appendChild( symbolizerElem );
2512 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2513 symbolizerElem.appendChild( strokeElem );
2516 QDomElement graphicStrokeElem = doc.createElement( QStringLiteral(
"se:GraphicStroke" ) );
2517 strokeElem.appendChild( graphicStrokeElem );
2522 markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
2526 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) ) );
2530 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"Missing marker line symbol layer. Skip it." ) ) );
2533 if ( !gap.isEmpty() )
2535 QDomElement gapElem = doc.createElement( QStringLiteral(
"se:Gap" ) );
2537 graphicStrokeElem.appendChild( gapElem );
2542 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
2545 symbolizerElem.appendChild( perpOffsetElem );
2554 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2555 if ( strokeElem.isNull() )
2558 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
2559 if ( graphicStrokeElem.isNull() )
2567 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2569 if ( it.key() == QLatin1String(
"placement" ) )
2571 if ( it.value() == QLatin1String(
"points" ) )
2573 else if ( it.value() == QLatin1String(
"firstPoint" ) )
2575 else if ( it.value() == QLatin1String(
"lastPoint" ) )
2577 else if ( it.value() == QLatin1String(
"centralPoint" ) )
2580 else if ( it.value() == QLatin1String(
"rotateMarker" ) )
2586 std::unique_ptr< QgsMarkerSymbol > marker;
2600 QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"Gap" ) );
2601 if ( !gapElem.isNull() )
2604 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
2610 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
2611 if ( !perpOffsetElem.isNull() )
2614 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2619 double scaleFactor = 1.0;
2620 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
2643 mMarker->setDataDefinedSize( property );
2650 const double prevOpacity =
mMarker->opacity();
2653 mMarker->setOpacity( prevOpacity );
2676 mMarker->renderPoint( point, feature, context, layer, selected );
2688 return mMarker->size( context );
2694 mMarker->setOutputUnit( unit );
2702 ||
mWidthUnit == Qgis::RenderUnit::MapUnits ||
mWidthUnit == Qgis::RenderUnit::MetersInMapUnits
2711 attr.unite(
mMarker->usedAttributes( context ) );
2726 return (
mMarker->size( context ) / 2.0 ) +
2748 if ( props.contains( QStringLiteral(
"interval" ) ) )
2749 interval = props[QStringLiteral(
"interval" )].toDouble();
2750 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2751 rotate = ( props[QStringLiteral(
"rotate" )] == QLatin1String(
"1" ) );
2753 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2755 if ( props.contains( QStringLiteral(
"hash_angle" ) ) )
2757 x->setHashAngle( props[QStringLiteral(
"hash_angle" )].toDouble() );
2760 if ( props.contains( QStringLiteral(
"hash_length" ) ) )
2761 x->setHashLength( props[QStringLiteral(
"hash_length" )].toDouble() );
2763 if ( props.contains( QStringLiteral(
"hash_length_unit" ) ) )
2766 if ( props.contains( QStringLiteral(
"hash_length_map_unit_scale" ) ) )
2774 return QStringLiteral(
"HashLine" );
2780 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2783 mHashSymbol->setRenderHints( hints );
2796 map[ QStringLiteral(
"hash_angle" ) ] = QString::number( mHashAngle );
2798 map[QStringLiteral(
"hash_length" )] = QString::number( mHashLength );
2807 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >(
rotateSymbols(),
interval() );
2809 x->setHashAngle( mHashAngle );
2810 x->setHashLength( mHashLength );
2811 x->setHashLengthUnit( mHashLengthUnit );
2812 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2818 mHashSymbol->setColor(
color );
2824 return mHashSymbol ? mHashSymbol->color() :
mColor;
2829 return mHashSymbol.get();
2840 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2841 mColor = mHashSymbol->color();
2847 mHashLength =
width;
2862 return ( mHashSymbol->width( context ) / 2.0 )
2870 mHashSymbol->setOutputUnit( unit );
2877 attr.unite( mHashSymbol->usedAttributes( context ) );
2885 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
2894 mHashSymbol->setDataDefinedWidth( property );
2901 return mHashLengthUnit == Qgis::RenderUnit::MapUnits || mHashLengthUnit == Qgis::RenderUnit::MetersInMapUnits
2905 ||
mWidthUnit == Qgis::RenderUnit::MapUnits ||
mWidthUnit == Qgis::RenderUnit::MetersInMapUnits
2907 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
2912 mSymbolLineAngle =
angle;
2917 return mSymbolAngle;
2922 mSymbolAngle =
angle;
2927 double lineLength = mHashLength;
2933 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
2947 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
2952 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
2969 const double prevOpacity = mHashSymbol->opacity();
2970 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
2972 mHashSymbol->setOpacity( prevOpacity );
2991 QPolygonF offsetPoints;
2994 renderLine( points, context, patternThickness, patternLength, brush );
3003 renderLine( part, context, patternThickness, patternLength, brush );
3008void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3009 const double patternLength,
const QBrush &sourceBrush )
3015 QBrush brush = sourceBrush;
3020 QPolygonF inputPoints;
3021 inputPoints.reserve( points.size() );
3023 double minX = std::numeric_limits< double >::max();
3024 double minY = std::numeric_limits< double >::max();
3025 double maxX = std::numeric_limits< double >::lowest();
3026 double maxY = std::numeric_limits< double >::lowest();
3028 for (
const QPointF &pt : std::as_const( points ) )
3035 minX = std::min( minX, pt.x() );
3036 minY = std::min( minY, pt.y() );
3037 maxX = std::max( maxX, pt.x() );
3038 maxY = std::max( maxY, pt.y() );
3041 if ( inputPoints.size() < 2 )
3045 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3047 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3050 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3051 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3053 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3054 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3056 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3057 if ( temporaryImage.isNull() )
3066 temporaryImage.fill( Qt::transparent );
3089 QPainterPathStroker stroker;
3090 stroker.setWidth( lineThickness );
3091 stroker.setCapStyle( cap );
3092 stroker.setJoinStyle( join );
3095 path.addPolygon( inputPoints );
3096 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3099 QPainter imagePainter;
3100 imagePainter.begin( &temporaryImage );
3102 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3104 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3105 imagePainter.setPen( Qt::NoPen );
3107 QPointF segmentStartPoint = inputPoints.at( 0 );
3110 double progressThroughImage = 0;
3112 QgsPoint prevSegmentPolygonEndLeft;
3113 QgsPoint prevSegmentPolygonEndRight;
3119 for (
int i = 1; i < inputPoints.size(); ++i )
3124 const QPointF segmentEndPoint = inputPoints.at( i );
3126 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3129 QgsPoint thisSegmentPolygonEndLeft;
3130 QgsPoint thisSegmentPolygonEndRight;
3132 QgsPoint thisSegmentPolygonEndLeftForPainter;
3133 QgsPoint thisSegmentPolygonEndRightForPainter;
3141 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3143 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3144 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3148 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtils::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3149 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3152 const QgsPoint lastSegmentStartPointLeft =
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3153 const QgsPoint lastSegmentEndPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3154 const QgsPoint lastSegmentStartPointRight =
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3155 const QgsPoint lastSegmentEndPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3161 bool isIntersection =
false;
3163 if ( !isIntersection )
3164 prevSegmentPolygonEndLeft = startPointLeft;
3165 isIntersection =
false;
3166 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3167 if ( !isIntersection )
3168 prevSegmentPolygonEndRight = startPointRight;
3170 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3171 startLinePolygonRight = prevSegmentPolygonEndRight;
3175 prevSegmentPolygonEndLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3176 if ( cap != Qt::PenCapStyle::FlatCap )
3177 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3178 prevSegmentPolygonEndRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3179 if ( cap != Qt::PenCapStyle::FlatCap )
3180 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3184 if ( i < inputPoints.size() - 1 )
3189 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3191 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3192 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3197 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3200 const QgsPoint nextSegmentStartPointLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3201 const QgsPoint nextSegmentEndPointLeft =
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3202 const QgsPoint nextSegmentStartPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3203 const QgsPoint nextSegmentEndPointRight =
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3209 bool isIntersection =
false;
3211 if ( !isIntersection )
3212 thisSegmentPolygonEndLeft = endPointLeft;
3213 isIntersection =
false;
3214 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3215 if ( !isIntersection )
3216 thisSegmentPolygonEndRight = endPointRight;
3218 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3219 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3227 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3228 thisSegmentPolygonEndRight = startLinePolygonRight;
3230 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3231 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3235 thisSegmentPolygonEndLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3236 if ( cap != Qt::PenCapStyle::FlatCap )
3237 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3238 thisSegmentPolygonEndRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3239 if ( cap != Qt::PenCapStyle::FlatCap )
3240 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3242 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3243 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3249 QTransform brushTransform;
3250 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3251 brushTransform.rotate( -segmentAngleDegrees );
3252 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3256 brushTransform.translate( -( lineThickness / 2 ), 0 );
3258 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3260 brush.setTransform( brushTransform );
3261 imagePainter.setBrush( brush );
3264 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3265 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3266 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3267 << prevSegmentPolygonEndRight.
toQPointF()
3268 << prevSegmentPolygonEndLeft.
toQPointF() );
3271 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3272 imagePainter.setBrush( Qt::NoBrush );
3273 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3274 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3275 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3276 << prevSegmentPolygonEndRight.
toQPointF()
3277 << prevSegmentPolygonEndLeft.
toQPointF() );
3278 imagePainter.setPen( Qt::NoPen );
3283 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3284 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3285 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3286 progressThroughImage = fmod( progressThroughImage, patternLength );
3289 segmentStartPoint = segmentEndPoint;
3290 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3291 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3299 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3300 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3317 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique<QgsRasterLineSymbolLayer>();
3319 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3321 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3323 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3327 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3332 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
3333 res->setPath(
properties[QStringLiteral(
"imageFile" )].toString() );
3335 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3337 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3339 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3343 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3348 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3350 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3353 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
3355 res->setOpacity(
properties[QStringLiteral(
"alpha" )].toDouble() );
3358 return res.release();
3365 map[QStringLiteral(
"imageFile" )] =
mPath;
3367 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3374 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3378 map[QStringLiteral(
"alpha" )] = QString::number(
mOpacity );
3385 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3397 return res.release();
3402 const QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
3403 if ( it !=
properties.end() && it.value().type() == QVariant::String )
3419 return QStringLiteral(
"RasterLine" );
3429 bool cached =
false;
3431 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3432 static_cast< int >( std::ceil( scaledHeight ) ) ),
3457 double strokeWidth =
mWidth;
3474 bool cached =
false;
3476 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3477 static_cast< int >( std::ceil( scaledHeight ) ) ),
3486 const QBrush brush( sourceImage );
3503 return Qgis::RenderUnit::Unknown;
3510 return mWidthUnit == Qgis::RenderUnit::MapUnits ||
mWidthUnit == Qgis::RenderUnit::MetersInMapUnits
3556 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique<QgsLineburstSymbolLayer>();
3558 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3560 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3562 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3566 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3571 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3573 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3575 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3579 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3584 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3586 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3589 if (
properties.contains( QStringLiteral(
"color_type" ) ) )
3592 if (
properties.contains( QStringLiteral(
"color" ) ) )
3596 if (
properties.contains( QStringLiteral(
"gradient_color2" ) ) )
3611 return res.release();
3618 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3625 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3631 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
3634#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
3646 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique< QgsLineburstSymbolLayer >();
3662 return res.release();
3667 return QStringLiteral(
"Lineburst" );
3683 double strokeWidth =
mWidth;
3702 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3713 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3725 gradient.setColorAt( 0.0, color1 );
3726 gradient.setColorAt( 1.0,
color2 );
3728 const QBrush brush( gradient );
3745 return Qgis::RenderUnit::Unknown;
3752 return mWidthUnit == Qgis::RenderUnit::MapUnits ||
mWidthUnit == Qgis::RenderUnit::MetersInMapUnits
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.
RenderUnit
Rendering size 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 * interiorRing(int i) const SIP_HOLDGIL
Retrieves an interior ring from the curve polygon.
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
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 SIP_HOLDGIL
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) SIP_HOLDGIL
Compute the intersection between two segments.
static double lineAngle(double x1, double y1, double x2, double y2) SIP_HOLDGIL
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 SIP_HOLDGIL
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 SIP_HOLDGIL
Returns the point as a QPointF.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const SIP_HOLDGIL
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.
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.
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style.
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.
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)
QLineF segment(int index, QRectF rect, double radius)
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.