39#include <QDomDocument>
45 : mPenStyle( penStyle )
49 mCustomDashVector << 5 << 2;
59 mCustomDashPatternUnit = unit;
60 mDashPatternOffsetUnit = unit;
61 mTrimDistanceStartUnit = unit;
62 mTrimDistanceEndUnit = unit;
86 mCustomDashPatternMapUnitScale = scale;
106 if ( props.contains( QStringLiteral(
"line_color" ) ) )
110 else if ( props.contains( QStringLiteral(
"outline_color" ) ) )
114 else if ( props.contains( QStringLiteral(
"color" ) ) )
119 if ( props.contains( QStringLiteral(
"line_width" ) ) )
121 width = props[QStringLiteral(
"line_width" )].toDouble();
123 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
125 width = props[QStringLiteral(
"outline_width" )].toDouble();
127 else if ( props.contains( QStringLiteral(
"width" ) ) )
130 width = props[QStringLiteral(
"width" )].toDouble();
132 if ( props.contains( QStringLiteral(
"line_style" ) ) )
136 else if ( props.contains( QStringLiteral(
"outline_style" ) ) )
140 else if ( props.contains( QStringLiteral(
"penstyle" ) ) )
146 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
150 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
154 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
159 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
161 if ( props.contains( QStringLiteral(
"offset" ) ) )
162 l->
setOffset( props[QStringLiteral(
"offset" )].toDouble() );
163 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
165 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
167 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
169 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
172 if ( props.contains( QStringLiteral(
"use_custom_dash" ) ) )
176 if ( props.contains( QStringLiteral(
"customdash" ) ) )
180 if ( props.contains( QStringLiteral(
"customdash_unit" ) ) )
184 if ( props.contains( QStringLiteral(
"customdash_map_unit_scale" ) ) )
189 if ( props.contains( QStringLiteral(
"draw_inside_polygon" ) ) )
194 if ( props.contains( QStringLiteral(
"ring_filter" ) ) )
199 if ( props.contains( QStringLiteral(
"dash_pattern_offset" ) ) )
201 if ( props.contains( QStringLiteral(
"dash_pattern_offset_unit" ) ) )
203 if ( props.contains( QStringLiteral(
"dash_pattern_offset_map_unit_scale" ) ) )
206 if ( props.contains( QStringLiteral(
"trim_distance_start" ) ) )
208 if ( props.contains( QStringLiteral(
"trim_distance_start_unit" ) ) )
210 if ( props.contains( QStringLiteral(
"trim_distance_start_map_unit_scale" ) ) )
212 if ( props.contains( QStringLiteral(
"trim_distance_end" ) ) )
214 if ( props.contains( QStringLiteral(
"trim_distance_end_unit" ) ) )
216 if ( props.contains( QStringLiteral(
"trim_distance_end_map_unit_scale" ) ) )
219 if ( props.contains( QStringLiteral(
"align_dash_pattern" ) ) )
222 if ( props.contains( QStringLiteral(
"tweak_dash_pattern_on_corners" ) ) )
232 return QStringLiteral(
"SimpleLine" );
244 mPen.setColor( penColor );
246 mPen.setWidthF( scaledWidth );
250 const double dashWidthDiv = std::max( 1.0, scaledWidth );
251 if ( mUseCustomDashPattern )
253 mPen.setStyle( Qt::CustomDashLine );
257 QVector<qreal> scaledVector;
258 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
259 for ( ; it != mCustomDashVector.constEnd(); ++it )
264 mPen.setDashPattern( scaledVector );
268 mPen.setStyle( mPenStyle );
271 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
276 mPen.setJoinStyle( mPenJoinStyle );
277 mPen.setCapStyle( mPenCapStyle );
282 selColor.setAlphaF( context.
opacity() );
283 mSelPen.setColor( selColor );
300 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
307 if ( mDrawInsidePolygon )
315 if ( mDrawInsidePolygon )
318 QPainterPath clipPath;
319 clipPath.addPolygon( points );
324 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
326 QPolygonF ring = *it;
327 clipPath.addPolygon( ring );
332 p->setClipPath( clipPath, Qt::IntersectClip );
355 for (
const QPolygonF &ring : std::as_const( *rings ) )
371 if ( mDrawInsidePolygon )
387 QPolygonF points = pts;
389 double startTrim = mTrimDistanceStart;
395 double endTrim = mTrimDistanceEnd;
402 double totalLength = -1;
406 startTrim = startTrim * 0.01 * totalLength;
414 if ( totalLength < 0 )
416 endTrim = endTrim * 0.01 * totalLength;
429 mPen.setColor( penColor );
432 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
435 const QPen pen = useSelectedColor ? mSelPen : mPen;
437 if ( !pen.dashPattern().isEmpty() )
440 const QVector<double> pattern = pen.dashPattern();
441 bool foundNonNull =
false;
442 for (
int i = 0; i < pattern.size(); ++i )
454 p->setBrush( Qt::NoBrush );
457 std::unique_ptr< QgsScopedQPainterState > painterState;
458 if ( points.size() <= 2 &&
461 ( p->renderHints() & QPainter::Antialiasing ) )
463 painterState = std::make_unique< QgsScopedQPainterState >( p );
464 p->setRenderHint( QPainter::Antialiasing,
false );
467 const bool applyPatternTweaks = mAlignDashPattern
468 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
469 && pen.dashOffset() == 0;
473 if ( applyPatternTweaks )
475 drawPathWithDashPatternTweaks( p, points, pen );
481 path.addPolygon( points );
496 for (
const QPolygonF &part : mline )
498 if ( applyPatternTweaks )
500 drawPathWithDashPatternTweaks( p, part, pen );
506 path.addPolygon( part );
517 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
523 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
526 map[QStringLiteral(
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
530 map[QStringLiteral(
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
533 map[QStringLiteral(
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
536 map[QStringLiteral(
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
539 map[QStringLiteral(
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
540 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
541 map[QStringLiteral(
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
542 map[QStringLiteral(
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
581 if ( mPenStyle == Qt::NoPen )
584 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
585 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
586 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
587 element.appendChild( symbolizerElem );
593 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
594 symbolizerElem.appendChild( strokeElem );
596 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
605 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
608 symbolizerElem.appendChild( perpOffsetElem );
614 if ( mUseCustomDashPattern )
617 mPen.color(), mPenJoinStyle,
618 mPenCapStyle,
mOffset, &mCustomDashVector );
631 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
632 if ( strokeElem.isNull() )
649 QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
650 if ( !perpOffsetElem.isNull() )
653 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
658 double scaleFactor = 1.0;
659 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
674void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
680 bool hasStrokeWidthExpression =
false;
687 pen.setWidthF( scaledWidth );
688 selPen.setWidthF( scaledWidth );
689 hasStrokeWidthExpression =
true;
698 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
699 pen.setColor( penColor );
713 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
717 QVector<qreal> dashVector;
721 QStringList dashList = exprVal.toString().split(
';' );
722 QStringList::const_iterator dashIt = dashList.constBegin();
723 for ( ; dashIt != dashList.constEnd(); ++dashIt )
727 pen.setDashPattern( dashVector );
734 QVector<qreal> scaledVector;
735 for (
double v : std::as_const( mCustomDashVector ) )
740 mPen.setDashPattern( scaledVector );
744 double patternOffset = mDashPatternOffset;
780void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
782 if ( pen.dashPattern().empty() || points.size() < 2 )
785 if ( pen.widthF() <= 1.0 )
787 pen.setWidthF( 1.0001 );
790 QVector< qreal > sourcePattern = pen.dashPattern();
791 const double dashWidthDiv = pen.widthF();
793 for (
int i = 0; i < sourcePattern.size(); ++ i )
794 sourcePattern[i] *= pen.widthF();
796 QVector< qreal > buffer;
797 QPolygonF bufferedPoints;
798 QPolygonF previousSegmentBuffer;
803 auto ptIt = points.constBegin();
804 double totalBufferLength = 0;
805 int patternIndex = 0;
806 double currentRemainingDashLength = 0;
807 double currentRemainingGapLength = 0;
809 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
811 QVector< qreal > result;
812 result.reserve( buffer.size() );
813 for (
auto it = buffer.begin(); it != buffer.end(); )
817 while ( dash == 0 && !result.empty() )
819 result.last() += gap;
821 if ( it == buffer.end() )
826 while ( gap == 0 && it != buffer.end() )
831 result << dash << gap;
836 double currentBufferLineLength = 0;
837 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
838 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
840 if ( buffer.empty() || bufferedPoints.size() < 2 )
845 if ( currentRemainingDashLength )
848 buffer << currentRemainingDashLength << 0.0;
849 totalBufferLength += currentRemainingDashLength;
851 QVector< qreal > compressed = compressPattern( buffer );
852 if ( !currentRemainingDashLength )
855 totalBufferLength -= compressed.last();
856 compressed.last() = 0;
860 const double scaleFactor = currentBufferLineLength / totalBufferLength;
862 bool shouldFlushPreviousSegmentBuffer =
false;
864 if ( !previousSegmentBuffer.empty() )
868 if ( !firstDashSubstring.empty() )
874 compressed = compressed.mid( 2 );
875 shouldFlushPreviousSegmentBuffer = !compressed.empty();
878 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
880 QPen adjustedPen = pen;
881 adjustedPen.setStyle( Qt::SolidLine );
882 painter->setPen( adjustedPen );
884 path.addPolygon( previousSegmentBuffer );
885 painter->drawPath( path );
886 previousSegmentBuffer.clear();
889 double finalDash = 0;
896 if ( !compressed.empty() )
898 finalDash = compressed.at( compressed.size() - 2 );
899 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
901 const QPolygonF thisPoints = bufferedPoints;
907 previousSegmentBuffer << bufferedPoints;
911 currentBufferLineLength = 0;
912 currentRemainingDashLength = 0;
913 currentRemainingGapLength = 0;
914 totalBufferLength = 0;
917 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
919 QPen adjustedPen = pen;
920 if ( !compressed.empty() )
923 compressed = compressed.mid( 0, 32 );
924 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
925 adjustedPen.setDashPattern( compressed );
929 adjustedPen.setStyle( Qt::SolidLine );
932 painter->setPen( adjustedPen );
934 path.addPolygon( bufferedPoints );
935 painter->drawPath( path );
938 bufferedPoints.clear();
944 bufferedPoints << p2;
945 for ( ; ptIt != points.constEnd(); ++ptIt )
953 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
954 currentBufferLineLength += remainingSegmentDistance;
958 if ( currentRemainingDashLength > 0 )
961 if ( remainingSegmentDistance >= currentRemainingDashLength )
964 buffer << currentRemainingDashLength << 0.0;
965 totalBufferLength += currentRemainingDashLength;
966 remainingSegmentDistance -= currentRemainingDashLength;
968 currentRemainingDashLength = 0.0;
969 currentRemainingGapLength = sourcePattern.at( patternIndex );
970 if ( currentRemainingGapLength == 0.0 )
978 buffer << remainingSegmentDistance << 0.0;
979 totalBufferLength += remainingSegmentDistance;
980 currentRemainingDashLength -= remainingSegmentDistance;
984 if ( currentRemainingGapLength > 0 )
987 if ( remainingSegmentDistance >= currentRemainingGapLength )
990 buffer << 0.0 << currentRemainingGapLength;
991 totalBufferLength += currentRemainingGapLength;
992 remainingSegmentDistance -= currentRemainingGapLength;
993 currentRemainingGapLength = 0.0;
999 buffer << 0.0 << remainingSegmentDistance;
1000 totalBufferLength += remainingSegmentDistance;
1001 currentRemainingGapLength -= remainingSegmentDistance;
1006 if ( patternIndex + 1 >= sourcePattern.size() )
1011 const double nextPatternDashLength = sourcePattern.at( patternIndex );
1012 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
1013 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1015 buffer << nextPatternDashLength << nextPatternGapLength;
1016 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1017 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1020 else if ( nextPatternDashLength <= remainingSegmentDistance )
1023 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1024 totalBufferLength += remainingSegmentDistance;
1025 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1026 currentRemainingDashLength = 0;
1033 buffer << remainingSegmentDistance << 0.0;
1034 totalBufferLength += remainingSegmentDistance;
1035 currentRemainingGapLength = 0;
1036 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1041 bufferedPoints << p1;
1042 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1044 QPointF nextPoint = *( ptIt + 1 );
1050 flushBuffer( &nextPoint );
1051 bufferedPoints << p1;
1054 if ( patternIndex % 2 == 1 )
1058 currentRemainingDashLength = sourcePattern.at( patternIndex );
1065 flushBuffer(
nullptr );
1066 if ( !previousSegmentBuffer.empty() )
1068 QPen adjustedPen = pen;
1069 adjustedPen.setStyle( Qt::SolidLine );
1070 painter->setPen( adjustedPen );
1072 path.addPolygon( previousSegmentBuffer );
1073 painter->drawPath( path );
1074 previousSegmentBuffer.clear();
1080 if ( mDrawInsidePolygon )
1094 unit = mCustomDashPatternUnit;
1095 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1132 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1137 return mAlignDashPattern;
1147 return mPatternCartographicTweakOnSharpCorners;
1152 mPatternCartographicTweakOnSharpCorners =
enabled;
1180 MyLine( QPointF p1, QPointF p2 )
1181 : mVertical( false )
1182 , mIncreasing( false )
1194 mIncreasing = ( p2.y() > p1.y() );
1199 mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
1200 mIncreasing = ( p2.x() > p1.x() );
1204 double x = ( p2.x() - p1.x() );
1205 double y = ( p2.y() - p1.y() );
1206 mLength = std::sqrt( x * x + y * y );
1212 double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
1220 QPointF diffForInterval(
double interval )
1223 return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
1225 double alpha = std::atan( mT );
1226 double dx = std::cos( alpha ) * interval;
1227 double dy = std::sin( alpha ) * interval;
1228 return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
1231 double length()
const {
return mLength; }
1246 : mRotateSymbols( rotateSymbol )
1247 , mInterval( interval )
1286 if ( mRenderingFeature )
1290 mFeatureSymbolOpacity = context.
opacity();
1291 mCurrentFeatureIsSelected = useSelectedColor;
1309 QString placementString = exprVal.toString();
1310 if ( placementString.compare( QLatin1String(
"interval" ), Qt::CaseInsensitive ) == 0 )
1314 else if ( placementString.compare( QLatin1String(
"vertex" ), Qt::CaseInsensitive ) == 0 )
1318 else if ( placementString.compare( QLatin1String(
"innervertices" ), Qt::CaseInsensitive ) == 0 )
1322 else if ( placementString.compare( QLatin1String(
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
1326 else if ( placementString.compare( QLatin1String(
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
1330 else if ( placementString.compare( QLatin1String(
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
1334 else if ( placementString.compare( QLatin1String(
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
1338 else if ( placementString.compare( QLatin1String(
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
1351 double averageOver = mAverageAngleLength;
1362 renderPolylineInterval( points, context, averageOver );
1364 renderPolylineCentral( points, context, averageOver );
1368 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1371 mHasRenderedFirstPart = mRenderingFeature;
1387 for (
int part = 0; part < mline.count(); ++part )
1389 const QPolygonF &points2 = mline[ part ];
1392 renderPolylineInterval( points2, context, averageOver );
1394 renderPolylineCentral( points2, context, averageOver );
1402 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1405 mHasRenderedFirstPart = mRenderingFeature;
1425 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1455 for (
int i = 0; i < rings->size(); ++i )
1488 mIntervalUnit = unit;
1489 mOffsetAlongLineUnit = unit;
1490 mAverageAngleLengthUnit = unit;
1515 map[QStringLiteral(
"rotate" )] = (
rotateSymbols() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1516 map[QStringLiteral(
"interval" )] = QString::number(
interval() );
1517 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
1518 map[QStringLiteral(
"offset_along_line" )] = QString::number(
offsetAlongLine() );
1525 map[QStringLiteral(
"average_angle_length" )] = QString::number( mAverageAngleLength );
1531 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
1532 map[QStringLiteral(
"place_on_every_part" )] = mPlaceOnEveryPart;
1538 return mPlaceOnEveryPart
1548 mRenderingFeature =
true;
1549 mHasRenderedFirstPart =
false;
1554 mRenderingFeature =
false;
1565 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1566 mFeatureSymbolOpacity = 1;
1595 if (
properties.contains( QStringLiteral(
"offset" ) ) )
1599 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
1603 if (
properties.contains( QStringLiteral(
"interval_unit" ) ) )
1607 if (
properties.contains( QStringLiteral(
"offset_along_line" ) ) )
1611 if (
properties.contains( QStringLiteral(
"offset_along_line_unit" ) ) )
1615 if (
properties.contains( ( QStringLiteral(
"offset_along_line_map_unit_scale" ) ) ) )
1620 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1624 if (
properties.contains( QStringLiteral(
"interval_map_unit_scale" ) ) )
1629 if (
properties.contains( QStringLiteral(
"average_angle_length" ) ) )
1633 if (
properties.contains( QStringLiteral(
"average_angle_unit" ) ) )
1637 if (
properties.contains( ( QStringLiteral(
"average_angle_map_unit_scale" ) ) ) )
1642 if (
properties.contains( QStringLiteral(
"placement" ) ) )
1644 if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"vertex" ) )
1646 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"lastvertex" ) )
1648 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"firstvertex" ) )
1650 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"centralpoint" ) )
1652 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"curvepoint" ) )
1654 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"segmentcenter" ) )
1659 else if (
properties.contains( QStringLiteral(
"placements" ) ) )
1665 if (
properties.contains( QStringLiteral(
"ring_filter" ) ) )
1675void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver )
1677 if ( points.isEmpty() )
1681 double lengthLeft = 0;
1713 if ( painterUnitInterval < 0 )
1716 double painterUnitOffsetAlongLine = 0;
1719 double totalLength = -1;
1740 if ( points.isClosed() )
1742 if ( painterUnitOffsetAlongLine > 0 )
1744 if ( totalLength < 0 )
1746 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1748 else if ( painterUnitOffsetAlongLine < 0 )
1750 if ( totalLength < 0 )
1752 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1764 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1766 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1768 QVector< QPointF > angleStartPoints;
1769 QVector< QPointF > symbolPoints;
1770 QVector< QPointF > angleEndPoints;
1778 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
1780 if ( symbolPoints.empty() )
1786 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1789 symbolPoints.pop_back();
1792 angleEndPoints.reserve( symbolPoints.size() );
1793 angleStartPoints.reserve( symbolPoints.size() );
1794 if ( averageOver <= painterUnitOffsetAlongLine )
1796 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
1800 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1802 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
1805 for (
int i = 0; i < symbolPoints.size(); ++ i )
1810 const QPointF pt = symbolPoints[i];
1811 const QPointF startPt = angleStartPoints[i];
1812 const QPointF endPt = angleEndPoints[i];
1814 MyLine l( startPt, endPt );
1829 QPointF lastPt = points[0];
1830 for (
int i = 1; i < points.count(); ++i )
1835 const QPointF &pt = points[i];
1841 MyLine l( lastPt, pt );
1842 QPointF diff = l.diffForInterval( painterUnitInterval );
1846 double c = 1 - lengthLeft / painterUnitInterval;
1848 lengthLeft += l.length();
1857 while ( lengthLeft > painterUnitInterval )
1861 lengthLeft -= painterUnitInterval;
1873static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1876 double a1 = MyLine( prevPt, pt ).angle();
1877 double a2 = MyLine( pt, nextPt ).angle();
1878 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1880 return std::atan2( unitY, unitX );
1885 if ( points.isEmpty() )
1890 int i = -1, maxCount = 0;
1891 bool isRing =
false;
1905 double totalLength = -1;
1925 if ( points.isClosed() )
1929 if ( totalLength < 0 )
1935 if ( totalLength < 0 )
2009 i = points.count() - 1;
2011 maxCount = points.count();
2019 maxCount = points.count() - 1;
2027 maxCount = points.count();
2028 if ( points.first() == points.last() )
2045 renderOffsetVertexAlongLine( points, i, distance, context,
placement );
2052 prevPoint = points.at( 0 );
2054 QPointF symbolPoint;
2055 for ( ; i < maxCount; ++i )
2066 QPointF currentPoint = points.at( i );
2067 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2068 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2071 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2072 currentPoint.x() - prevPoint.x() );
2075 prevPoint = currentPoint;
2079 symbolPoint = points.at( i );
2083 double angle = markerAngle( points, isRing, i );
2088 mFinalVertex = symbolPoint;
2094double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2097 const QPointF &pt = points[vertex];
2099 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2101 int prevIndex = vertex - 1;
2102 int nextIndex = vertex + 1;
2104 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2106 prevIndex = points.count() - 2;
2110 QPointF prevPoint, nextPoint;
2111 while ( prevIndex >= 0 )
2113 prevPoint = points[ prevIndex ];
2114 if ( prevPoint != pt )
2121 while ( nextIndex < points.count() )
2123 nextPoint = points[ nextIndex ];
2124 if ( nextPoint != pt )
2131 if ( prevIndex >= 0 && nextIndex < points.count() )
2133 angle = _averageAngle( prevPoint, pt, nextPoint );
2140 while ( vertex < points.size() - 1 )
2142 const QPointF &nextPt = points[vertex + 1];
2145 angle = MyLine( pt, nextPt ).angle();
2154 while ( vertex >= 1 )
2156 const QPointF &prevPt = points[vertex - 1];
2159 angle = MyLine( prevPt, pt ).angle();
2171 if ( points.isEmpty() )
2181 bool isRing =
false;
2182 if ( points.first() == points.last() )
2184 double angle = markerAngle( points, isRing, vertex );
2187 mFinalVertex = points[vertex];
2193 int pointIncrement = distance > 0 ? 1 : -1;
2194 QPointF previousPoint = points[vertex];
2195 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2196 int endPoint = distance > 0 ? points.count() - 1 : 0;
2197 double distanceLeft = std::fabs( distance );
2199 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2201 const QPointF &pt = points[i];
2203 if ( previousPoint == pt )
2207 MyLine l( previousPoint, pt );
2209 if ( distanceLeft < l.length() )
2212 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2218 mFinalVertex = markerPoint;
2224 distanceLeft -= l.length();
2231void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
double initialLag,
int numberPointsRequired )
2236 QVector< QPointF > points = p;
2237 const bool closedRing = points.first() == points.last();
2239 double lengthLeft = initialOffset;
2241 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2242 if ( initialLagLeft < 0 && closedRing )
2245 QPointF lastPt = points.constLast();
2246 QVector< QPointF > pseudoPoints;
2247 for (
int i = points.count() - 2; i > 0; --i )
2249 if ( initialLagLeft >= 0 )
2254 const QPointF &pt = points[i];
2259 MyLine l( lastPt, pt );
2260 initialLagLeft += l.length();
2265 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2267 points = pseudoPoints;
2272 while ( initialLagLeft < 0 )
2274 dest << points.constFirst();
2275 initialLagLeft += intervalPainterUnits;
2278 if ( initialLag > 0 )
2280 lengthLeft += intervalPainterUnits - initialLagLeft;
2283 QPointF lastPt = points[0];
2284 for (
int i = 1; i < points.count(); ++i )
2286 const QPointF &pt = points[i];
2290 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2299 MyLine l( lastPt, pt );
2300 QPointF diff = l.diffForInterval( intervalPainterUnits );
2304 double c = 1 - lengthLeft / intervalPainterUnits;
2306 lengthLeft += l.length();
2309 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2313 lengthLeft -= intervalPainterUnits;
2316 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2321 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2325 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2332 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2335 while ( dest.size() < numberPointsRequired )
2336 dest << points.constLast();
2340void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver )
2342 if ( !points.isEmpty() )
2346 QPolygonF::const_iterator it = points.constBegin();
2348 for ( ++it; it != points.constEnd(); ++it )
2350 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2351 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2357 const double midPoint = length / 2;
2360 double thisSymbolAngle = 0;
2362 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2364 QVector< QPointF > angleStartPoints;
2365 QVector< QPointF > symbolPoints;
2366 QVector< QPointF > angleEndPoints;
2368 collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
2369 collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
2370 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
2372 pt = symbolPoints.at( 1 );
2373 MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2374 thisSymbolAngle = l.angle();
2379 it = points.constBegin();
2381 qreal last_at = 0, next_at = 0;
2383 for ( ++it; it != points.constEnd(); ++it )
2386 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2387 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2388 if ( next_at >= midPoint )
2395 MyLine l( last, next );
2396 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2397 pt = last + ( next - last ) * k;
2398 thisSymbolAngle = l.angle();
2450 if ( props.contains( QStringLiteral(
"interval" ) ) )
2451 interval = props[QStringLiteral(
"interval" )].toDouble();
2452 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2453 rotate = ( props[QStringLiteral(
"rotate" )].toString() == QLatin1String(
"1" ) );
2455 auto x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2462 return QStringLiteral(
"MarkerLine" );
2482 mMarker->setRenderHints( hints );
2502 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2504 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
2505 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2506 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2507 element.appendChild( symbolizerElem );
2537 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2538 symbolizerElem.appendChild( strokeElem );
2541 QDomElement graphicStrokeElem = doc.createElement( QStringLiteral(
"se:GraphicStroke" ) );
2542 strokeElem.appendChild( graphicStrokeElem );
2547 markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
2551 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) ) );
2555 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"Missing marker line symbol layer. Skip it." ) ) );
2558 if ( !gap.isEmpty() )
2560 QDomElement gapElem = doc.createElement( QStringLiteral(
"se:Gap" ) );
2562 graphicStrokeElem.appendChild( gapElem );
2567 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
2570 symbolizerElem.appendChild( perpOffsetElem );
2579 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2580 if ( strokeElem.isNull() )
2583 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
2584 if ( graphicStrokeElem.isNull() )
2592 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2594 if ( it.key() == QLatin1String(
"placement" ) )
2596 if ( it.value() == QLatin1String(
"points" ) )
2598 else if ( it.value() == QLatin1String(
"firstPoint" ) )
2600 else if ( it.value() == QLatin1String(
"lastPoint" ) )
2602 else if ( it.value() == QLatin1String(
"centralPoint" ) )
2605 else if ( it.value() == QLatin1String(
"rotateMarker" ) )
2611 std::unique_ptr< QgsMarkerSymbol > marker;
2625 QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"Gap" ) );
2626 if ( !gapElem.isNull() )
2629 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
2635 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
2636 if ( !perpOffsetElem.isNull() )
2639 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2644 double scaleFactor = 1.0;
2645 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
2668 mMarker->setDataDefinedSize( property );
2675 const double prevOpacity =
mMarker->opacity();
2678 mMarker->setOpacity( prevOpacity );
2683 mMarker->setLineAngle( angle );
2701 mMarker->renderPoint( point, feature, context, layer, selected );
2713 return mMarker->size( context );
2719 mMarker->setOutputUnit( unit );
2736 attr.unite(
mMarker->usedAttributes( context ) );
2751 return (
mMarker->size( context ) / 2.0 ) +
2773 if ( props.contains( QStringLiteral(
"interval" ) ) )
2774 interval = props[QStringLiteral(
"interval" )].toDouble();
2775 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2776 rotate = ( props[QStringLiteral(
"rotate" )] == QLatin1String(
"1" ) );
2778 auto x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2780 if ( props.contains( QStringLiteral(
"hash_angle" ) ) )
2782 x->setHashAngle( props[QStringLiteral(
"hash_angle" )].toDouble() );
2785 if ( props.contains( QStringLiteral(
"hash_length" ) ) )
2786 x->setHashLength( props[QStringLiteral(
"hash_length" )].toDouble() );
2788 if ( props.contains( QStringLiteral(
"hash_length_unit" ) ) )
2791 if ( props.contains( QStringLiteral(
"hash_length_map_unit_scale" ) ) )
2799 return QStringLiteral(
"HashLine" );
2808 mHashSymbol->setRenderHints( hints );
2821 map[ QStringLiteral(
"hash_angle" ) ] = QString::number( mHashAngle );
2823 map[QStringLiteral(
"hash_length" )] = QString::number( mHashLength );
2834 x->setHashAngle( mHashAngle );
2835 x->setHashLength( mHashLength );
2836 x->setHashLengthUnit( mHashLengthUnit );
2837 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2843 mHashSymbol->setColor(
color );
2849 return mHashSymbol ? mHashSymbol->color() :
mColor;
2854 return mHashSymbol.get();
2865 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2866 mColor = mHashSymbol->color();
2872 mHashLength =
width;
2887 return ( mHashSymbol->width( context ) / 2.0 )
2895 mHashSymbol->setOutputUnit( unit );
2902 attr.unite( mHashSymbol->usedAttributes( context ) );
2910 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
2919 mHashSymbol->setDataDefinedWidth( property );
2932 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
2937 mSymbolLineAngle = angle;
2942 return mSymbolAngle;
2947 mSymbolAngle = angle;
2952 double lineLength = mHashLength;
2958 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
2972 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
2977 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
2994 const double prevOpacity = mHashSymbol->opacity();
2995 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
2997 mHashSymbol->setOpacity( prevOpacity );
3016 QPolygonF offsetPoints;
3019 renderLine( points, context, patternThickness, patternLength, brush );
3028 renderLine( part, context, patternThickness, patternLength, brush );
3033void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3034 const double patternLength,
const QBrush &sourceBrush )
3040 QBrush brush = sourceBrush;
3045 QPolygonF inputPoints;
3046 inputPoints.reserve( points.size() );
3048 double minX = std::numeric_limits< double >::max();
3049 double minY = std::numeric_limits< double >::max();
3050 double maxX = std::numeric_limits< double >::lowest();
3051 double maxY = std::numeric_limits< double >::lowest();
3053 for (
const QPointF &pt : std::as_const( points ) )
3060 minX = std::min( minX, pt.x() );
3061 minY = std::min( minY, pt.y() );
3062 maxX = std::max( maxX, pt.x() );
3063 maxY = std::max( maxY, pt.y() );
3066 if ( inputPoints.size() < 2 )
3070 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3072 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3075 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3076 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3078 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3079 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3081 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3082 if ( temporaryImage.isNull() )
3091 temporaryImage.fill( Qt::transparent );
3114 QPainterPathStroker stroker;
3115 stroker.setWidth( lineThickness );
3116 stroker.setCapStyle( cap );
3117 stroker.setJoinStyle( join );
3120 path.addPolygon( inputPoints );
3121 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3124 QPainter imagePainter;
3125 imagePainter.begin( &temporaryImage );
3127 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3129 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3130 imagePainter.setPen( Qt::NoPen );
3132 QPointF segmentStartPoint = inputPoints.at( 0 );
3135 double progressThroughImage = 0;
3137 QgsPoint prevSegmentPolygonEndLeft;
3138 QgsPoint prevSegmentPolygonEndRight;
3144 for (
int i = 1; i < inputPoints.size(); ++i )
3149 const QPointF segmentEndPoint = inputPoints.at( i );
3151 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3154 QgsPoint thisSegmentPolygonEndLeft;
3155 QgsPoint thisSegmentPolygonEndRight;
3157 QgsPoint thisSegmentPolygonEndLeftForPainter;
3158 QgsPoint thisSegmentPolygonEndRightForPainter;
3166 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3168 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3169 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3173 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtilsBase::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3174 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3177 const QgsPoint lastSegmentStartPointLeft =
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3178 const QgsPoint lastSegmentEndPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3179 const QgsPoint lastSegmentStartPointRight =
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3180 const QgsPoint lastSegmentEndPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3186 bool isIntersection =
false;
3188 if ( !isIntersection )
3189 prevSegmentPolygonEndLeft = startPointLeft;
3190 isIntersection =
false;
3191 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3192 if ( !isIntersection )
3193 prevSegmentPolygonEndRight = startPointRight;
3195 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3196 startLinePolygonRight = prevSegmentPolygonEndRight;
3200 prevSegmentPolygonEndLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3201 if ( cap != Qt::PenCapStyle::FlatCap )
3202 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3203 prevSegmentPolygonEndRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3204 if ( cap != Qt::PenCapStyle::FlatCap )
3205 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3209 if ( i < inputPoints.size() - 1 )
3214 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3216 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3217 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3222 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3225 const QgsPoint nextSegmentStartPointLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3226 const QgsPoint nextSegmentEndPointLeft =
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3227 const QgsPoint nextSegmentStartPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3228 const QgsPoint nextSegmentEndPointRight =
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3234 bool isIntersection =
false;
3236 if ( !isIntersection )
3237 thisSegmentPolygonEndLeft = endPointLeft;
3238 isIntersection =
false;
3239 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3240 if ( !isIntersection )
3241 thisSegmentPolygonEndRight = endPointRight;
3243 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3244 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3252 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3253 thisSegmentPolygonEndRight = startLinePolygonRight;
3255 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3256 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3260 thisSegmentPolygonEndLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3261 if ( cap != Qt::PenCapStyle::FlatCap )
3262 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3263 thisSegmentPolygonEndRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3264 if ( cap != Qt::PenCapStyle::FlatCap )
3265 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3267 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3268 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3274 QTransform brushTransform;
3275 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3276 brushTransform.rotate( -segmentAngleDegrees );
3277 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3281 brushTransform.translate( -( lineThickness / 2 ), 0 );
3283 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3285 brush.setTransform( brushTransform );
3286 imagePainter.setBrush( brush );
3289 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3290 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3291 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3292 << prevSegmentPolygonEndRight.
toQPointF()
3293 << prevSegmentPolygonEndLeft.
toQPointF() );
3296 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3297 imagePainter.setBrush( Qt::NoBrush );
3298 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3299 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3300 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3301 << prevSegmentPolygonEndRight.
toQPointF()
3302 << prevSegmentPolygonEndLeft.
toQPointF() );
3303 imagePainter.setPen( Qt::NoPen );
3308 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3309 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3310 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3311 progressThroughImage = fmod( progressThroughImage, patternLength );
3314 segmentStartPoint = segmentEndPoint;
3315 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3316 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3324 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3325 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3342 auto res = std::make_unique<QgsRasterLineSymbolLayer>();
3344 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3346 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3348 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3352 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3357 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
3358 res->setPath(
properties[QStringLiteral(
"imageFile" )].toString() );
3360 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3362 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3364 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3368 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3373 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3375 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3378 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
3380 res->setOpacity(
properties[QStringLiteral(
"alpha" )].toDouble() );
3383 return res.release();
3390 map[QStringLiteral(
"imageFile" )] =
mPath;
3392 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3399 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3403 map[QStringLiteral(
"alpha" )] = QString::number(
mOpacity );
3410 auto res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3422 return res.release();
3427 const QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
3428 if ( it !=
properties.end() && it.value().userType() == QMetaType::Type::QString )
3444 return QStringLiteral(
"RasterLine" );
3459 bool cached =
false;
3461 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3462 static_cast< int >( std::ceil( scaledHeight ) ) ),
3487 double strokeWidth =
mWidth;
3504 bool cached =
false;
3506 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3507 static_cast< int >( std::ceil( scaledHeight ) ) ),
3512 if ( useSelectedColor )
3517 const QBrush brush( sourceImage );
3587 auto res = std::make_unique<QgsLineburstSymbolLayer>();
3589 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3591 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3593 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3597 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3602 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3604 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3606 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3610 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3615 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3617 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3620 if (
properties.contains( QStringLiteral(
"color_type" ) ) )
3623 if (
properties.contains( QStringLiteral(
"color" ) ) )
3627 if (
properties.contains( QStringLiteral(
"gradient_color2" ) ) )
3642 return res.release();
3649 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3656 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3662 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
3673 auto res = std::make_unique< QgsLineburstSymbolLayer >();
3689 return res.release();
3694 return QStringLiteral(
"Lineburst" );
3715 double strokeWidth =
mWidth;
3731 if ( useSelectedColor )
3735 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3746 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3758 gradient.setColorAt( 0.0, color1 );
3759 gradient.setColorAt( 1.0,
color2 );
3761 const QBrush brush( gradient );
3840 if ( props.contains( QStringLiteral(
"line_width" ) ) )
3842 width = props[QStringLiteral(
"line_width" )].toDouble();
3844 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
3846 width = props[QStringLiteral(
"outline_width" )].toDouble();
3848 else if ( props.contains( QStringLiteral(
"width" ) ) )
3850 width = props[QStringLiteral(
"width" )].toDouble();
3855 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
3859 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
3863 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
3868 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3870 if ( props.contains( QStringLiteral(
"offset" ) ) )
3871 l->setOffset( props[QStringLiteral(
"offset" )].toDouble() );
3872 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
3874 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3876 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
3878 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
3881 l->restoreOldDataDefinedProperties( props );
3888 return QStringLiteral(
"FilledLine" );
3937 Qt::PenJoinStyle join = mPenJoinStyle;
3946 Qt::PenCapStyle cap = mPenCapStyle;
3962 const double prevOpacity = mFill->opacity();
3963 mFill->setOpacity( mFill->opacity() * context.
opacity() );
3970 if ( points.count() >= 2 )
3973 geos::unique_ptr lineGeom;
3988 auto inputPoly = std::make_unique< QgsPolygon >(
static_cast< QgsLineString *
>( ls.release() ) );
3994 if ( !parts.empty() )
4016 geos::unique_ptr buffered =
QgsGeos::buffer( lineGeom.get(), scaledWidth / 2, 8,
4022 std::unique_ptr< QgsAbstractGeometry > bufferedGeom =
QgsGeos::fromGeos( buffered.get() );
4024 for (
const QList< QPolygonF > &polygon : parts )
4026 QVector< QPolygonF > rings;
4027 for (
int i = 1; i < polygon.size(); ++i )
4028 rings << polygon.at( i );
4029 mFill->renderPolygon( polygon.value( 0 ), &rings, context.
feature(), context.
renderContext(), -1, useSelectedColor );
4037 mFill->setOpacity( prevOpacity );
4044 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
4049 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
4064 res->setSubSymbol( mFill->clone() );
4065 return res.release();
4100 attr.unite( mFill->usedAttributes( context ) );
4108 if ( mFill && mFill->hasDataDefinedProperties() )
4117 mFill->setColor(
c );
4122 return mFill ? mFill->color() :
mColor;
4129 || ( mFill && mFill->usesMapUnits() );
4136 mFill->setMapUnitScale( scale );
4143 return mFill->mapUnitScale();
4152 mFill->setOutputUnit( unit );
4159 return mFill->outputUnit();
MarkerLinePlacement
Defines how/where the symbols should be placed on a line.
@ CurvePoint
Place symbols at every virtual curve point in the line (used when rendering curved geometry types onl...
@ InnerVertices
Inner vertices (i.e. all vertices except the first and last vertex)
@ LastVertex
Place symbols on the last vertex in the line.
@ CentralPoint
Place symbols at the mid point of the line.
@ SegmentCenter
Place symbols at the center of every line segment.
@ Vertex
Place symbols on every vertex in the line.
@ Interval
Place symbols at regular intervals.
@ FirstVertex
Place symbols on the first vertex in the line.
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
@ IsSymbolLayerSubSymbol
Symbol is being rendered as a sub-symbol of a QgsSymbolLayer.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
GradientColorSource
Gradient color sources.
@ ColorRamp
Gradient color ramp.
@ CanCalculateMaskGeometryPerFeature
If present, indicates that mask geometry can safely be calculated per feature for the symbol layer....
@ Curve
An intermediate point on a segment defining the curvature of the segment.
@ Segment
The actual start or end point of a segment.
QFlags< SymbolLayerFlag > SymbolLayerFlags
Symbol layer flags.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
@ Miter
Use mitered joins.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes)
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
@ Flat
Flat cap (in line with start/end of line)
@ RenderingSubSymbol
Set whenever a sub-symbol of a parent symbol is currently being rendered. Can be used during symbol a...
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
@ MultiLineString
MultiLineString.
QFlags< MarkerLinePlacement > MarkerLinePlacements
Base class for line symbol layer types which draws line sections using a QBrush.
Qt::PenCapStyle mPenCapStyle
Qt::PenJoinStyle mPenJoinStyle
void renderPolylineUsingBrush(const QPolygonF &points, QgsSymbolRenderContext &context, const QBrush &brush, double patternThickness, double patternLength)
Renders a polyline of points using the specified brush.
static bool isGeneralizableByDeviceBoundingBox(const QgsRectangle &envelope, float mapToPixelTol=1.0f)
Returns whether the device-envelope can be replaced by its BBOX when is applied the specified toleran...
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
Abstract base class for color ramps.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Curve polygon geometry type.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Exports QGIS layers to the DXF format.
static double mapUnitScaleFactor(double scale, Qgis::RenderUnit symbolUnits, Qgis::DistanceUnit mapUnits, double mapUnitsPerPixel=1.0)
Returns scale factor for conversion to map units.
Qgis::DistanceUnit mapUnits() const
Retrieve map units.
double symbologyScale() const
Returns the reference scale for output.
void clipValueToMapUnitScale(double &value, const QgsMapUnitScale &scale, double pixelToMMFactor) const
Clips value to scale minimum/maximum.
RAII class to pop scope from an expression context on destruction.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
static const QString EXPR_GEOMETRY_POINT_COUNT
Inbuilt variable name for point count variable.
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
static const QString EXPR_GEOMETRY_RING_NUM
Inbuilt variable name for geometry ring number variable.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isCanceled() const
Tells whether the operation has been canceled already.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
A line symbol layer type which fills a stroked line with a QgsFillSymbol.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString layerType() const override
Returns a string that represents this layer type.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFilledLineSymbolLayer, using the settings serialized in the properties map (correspo...
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
~QgsFilledLineSymbolLayer() override
QgsFilledLineSymbolLayer(double width=DEFAULT_SIMPLELINE_WIDTH, QgsFillSymbol *fillSymbol=nullptr)
Constructor for QgsFilledLineSymbolLayer.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setColor(const QColor &c) override
Sets the "representative" color for the symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
QgsFilledLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
QgsMapUnitScale mapUnitScale() const override
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static bool segmentIntersection(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
A geometry is the spatial representation of a feature.
QVector< QgsGeometry > coerceToType(Qgis::WkbType type, double defaultZ=0, double defaultM=0) const
Attempts to coerce this geometry into the specified destination type.
static geos::unique_ptr offsetCurve(const GEOSGeometry *geometry, double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg=nullptr)
Directly calculates the offset curve for a GEOS geometry object and returns a GEOS geometry result.
QgsAbstractGeometry * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlags())
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
void addStopsToGradient(QGradient *gradient, double opacity=1) const
Copy color ramp stops to a QGradient.
Line symbol layer type which draws repeating line sections along a line feature.
double hashAngle() const
Returns the angle to use when drawing the hashed lines sections, in degrees clockwise.
QgsHashedLineSymbolLayer(bool rotateSymbol=true, double interval=3)
Constructor for QgsHashedLineSymbolLayer.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setWidth(double width) override
Sets the width of the line symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
double width() const override
Returns the estimated width for the line symbol layer.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsHashedLineSymbolLayer, using the settings serialized in the properties map (correspo...
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsHashedLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
~QgsHashedLineSymbolLayer() override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QColor color() const override
Returns the "representative" color of the symbol layer.
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString layerType() const override
Returns a string that represents this layer type.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setHashAngle(double angle)
Sets the angle to use when drawing the hashed lines sections, in degrees clockwise.
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
static void overlayColor(QImage &image, const QColor &color)
Overlays a color onto an image.
Line string geometry type, with support for z-dimension and m-values.
static std::unique_ptr< QgsLineString > fromQPolygonF(const QPolygonF &polygon)
Returns a new linestring from a QPolygonF polygon input.
Abstract base class for line symbol layers.
Qgis::RenderUnit mOffsetUnit
RenderRingFilter
Options for filtering rings when the line symbol layer is being used to render a polygon's rings.
@ ExteriorRingOnly
Render the exterior ring only.
@ InteriorRingsOnly
Render the interior rings only.
@ AllRings
Render both exterior and interior rings.
QgsMapUnitScale mWidthMapUnitScale
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void setWidthMapUnitScale(const QgsMapUnitScale &scale)
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit mWidthUnit
void setOffset(double offset)
Sets the line's offset.
RenderRingFilter mRingFilter
void setOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the line's offset.
void setWidthUnit(Qgis::RenderUnit unit)
Sets the units for the line's width.
virtual double width() const
Returns the estimated width for the line symbol layer.
QgsMapUnitScale mOffsetMapUnitScale
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the line's offset.
QgsMapUnitScale mapUnitScale() const override
void setRingFilter(QgsLineSymbolLayer::RenderRingFilter filter)
Sets the line symbol layer's ring filter, which controls which rings are rendered when the line symbo...
void setMapUnitScale(const QgsMapUnitScale &scale) override
double offset() const
Returns the line's offset.
Qgis::RenderUnit offsetUnit() const
Returns the units for the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
Line symbol layer type which draws a gradient pattern perpendicularly along a line.
std::unique_ptr< QgsColorRamp > mGradientRamp
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp used for the gradient line.
QColor color2() const
Returns the color for endpoint of gradient, only used if the gradient color type is set to SimpleTwoC...
Qgis::GradientColorSource mGradientColorType
QString layerType() const override
Returns a string that represents this layer type.
~QgsLineburstSymbolLayer() override
QgsLineburstSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsMapUnitScale mapUnitScale() const override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsLineburstSymbolLayer, using the settings serialized in the properties map (correspon...
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QgsLineburstSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, const QColor &color2=Qt::white)
Constructor for QgsLineburstSymbolLayer, with the specified start and end gradient colors.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsColorRamp * colorRamp()
Returns the color ramp used for the gradient line.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
void transformInPlace(double &x, double &y) const
Transforms map coordinates to device coordinates.
Struct for storing maximum and minimum scales for measurements in map units.
Line symbol layer type which draws repeating marker symbols along a line feature.
Q_DECL_DEPRECATED bool rotateMarker() const
Shall the marker be rotated.
std::unique_ptr< QgsMarkerSymbol > mMarker
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsMarkerLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
double width() const override
Returns the estimated width for the line symbol layer.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsMarkerLineSymbolLayer, using the settings serialized in the properties map (correspo...
QgsMarkerLineSymbolLayer(bool rotateMarker=DEFAULT_MARKERLINE_ROTATE, double interval=DEFAULT_MARKERLINE_INTERVAL)
Constructor for QgsMarkerLineSymbolLayer.
void setWidth(double width) override
Sets the width of the line symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
~QgsMarkerLineSymbolLayer() override
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QString layerType() const override
Returns a string that represents this layer type.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsMarkerLineSymbolLayer from an SLD XML DOM element.
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
Abstract base class for marker symbol layers.
A marker symbol type, for rendering Point and MultiPoint geometries.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Resolves relative paths into absolute paths and vice versa.
A class to represent a 2D point.
QgsPointXY project(double distance, double bearing) const
Returns a new point which corresponds to this point projected by a specified distance in a specified ...
Point geometry type, with support for z-dimension and m-values.
QPointF toQPointF() const
Returns the point as a QPointF.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const final
Returns the calculated value of the property with the specified key from within the collection.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
A store for object properties.
Line symbol layer type which draws line sections using a raster image file.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QgsRasterLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
double opacity() const
Returns the line opacity.
QString path() const
Returns the raster image path.
void setPath(const QString &path)
Set the raster image path.
QString layerType() const override
Returns a string that represents this layer type.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
QgsRasterLineSymbolLayer(const QString &path=QString())
Constructor for QgsRasterLineSymbolLayer, with the specified raster image path.
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsRasterLineSymbolLayer, using the settings serialized in the properties map (correspo...
QColor color() const override
Returns the "representative" color of the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsMapUnitScale mapUnitScale() const override
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
virtual ~QgsRasterLineSymbolLayer()
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
QgsVectorSimplifyMethod & vectorSimplifyMethod()
Returns the simplification settings to use when rendering vector layers.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QColor selectionColor() const
Returns the color to use when rendering selected features.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
const QgsAbstractGeometry * geometry() const
Returns pointer to the unsegmentized geometry.
Scoped object for saving and restoring a QPainter object's state.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void setDrawInsidePolygon(bool drawInsidePolygon)
Sets whether the line should only be drawn inside polygons, and any portion of the line which falls o...
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QgsMapUnitScale mapUnitScale() const override
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QVector< qreal > customDashVector() const
Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the outline of polygon, using the given render context.
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
void setCustomDashPatternMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for lengths used in the custom dash pattern.
void setTrimDistanceEndMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the end of the line.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void setTrimDistanceEnd(double distance)
Sets the trim distance for the end of the line, which dictates a length from the end of the line at w...
double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets offset.
QgsSimpleLineSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, double width=DEFAULT_SIMPLELINE_WIDTH, Qt::PenStyle penStyle=DEFAULT_SIMPLELINE_PENSTYLE)
Constructor for QgsSimpleLineSymbolLayer.
~QgsSimpleLineSymbolLayer() override
void setUseCustomDashPattern(bool b)
Sets whether the line uses a custom dash pattern.
void setTweakDashPatternOnCorners(bool enabled)
Sets whether dash patterns tweaks should be applied on sharp corners, to ensure that a double-length ...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
void setCustomDashVector(const QVector< qreal > &vector)
Sets the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ren...
void setDashPatternOffset(double offset)
Sets the dash pattern offset, which dictates how far along the dash pattern the pattern should start ...
QColor dxfColor(QgsSymbolRenderContext &context) const override
Gets color.
QString layerType() const override
Returns a string that represents this layer type.
void setDashPatternOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the dash pattern offset.
QgsSimpleLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
void setAlignDashPattern(bool enabled)
Sets whether dash patterns should be aligned to the start and end of lines, by applying subtle tweaks...
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleLineSymbolLayer from an SLD XML DOM element.
double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets line width.
void setTrimDistanceStartMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the start of the line.
QVector< qreal > dxfCustomDashPattern(Qgis::RenderUnit &unit) const override
Gets dash pattern.
Qt::PenCapStyle penCapStyle() const
Returns the pen cap style used to render the line (e.g.
void setTrimDistanceEndUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the end of the line.
void setDashPatternOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the dash pattern offset.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setTrimDistanceStart(double distance)
Sets the trim distance for the start of the line, which dictates a length from the start of the line ...
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setTrimDistanceStartUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the start of the line.
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
void setCustomDashPatternUnit(Qgis::RenderUnit unit)
Sets the unit for lengths used in the custom dash pattern.
static QString encodePenStyle(Qt::PenStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static 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 Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static Qt::PenStyle decodePenStyle(const QString &str)
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static QString encodeRealVector(const QVector< qreal > &v)
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
bool shouldRenderUsingSelectionColor(const QgsSymbolRenderContext &context) const
Returns true if the symbol layer should be rendered using the selection color from the render context...
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
bool installMasks(QgsRenderContext &context, bool recursive, const QRectF &rect=QRectF())
When rendering, install masks on context painter.
void removeMasks(QgsRenderContext &context, bool recursive)
When rendering, remove previously installed masks from context painter if recursive is true masks are...
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
Property
Data definable properties.
@ SecondaryColor
Secondary color (eg for gradient fills)
@ File
Filename, eg for svg files.
@ DashPatternOffset
Dash pattern offset,.
@ OffsetAlongLine
Offset along line.
@ CustomDash
Custom dash pattern.
@ StrokeStyle
Stroke style (eg solid, dashed)
@ StrokeColor
Stroke color.
@ TrimStart
Trim distance from start of line.
@ CapStyle
Line cap style.
@ Placement
Line marker placement.
@ LineAngle
Line angle, or angle of hash lines for hash line symbols.
@ JoinStyle
Line join style.
@ AverageAngleLength
Length to average symbol angles over.
@ Interval
Line marker interval.
@ StrokeWidth
Stroke width.
@ LineDistance
Distance between lines, or length of lines for hash line symbols.
@ TrimEnd
Trim distance from end of line.
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
virtual Qgis::SymbolLayerFlags flags() const
Returns flags which control the symbol layer's behavior.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
const QgsFeature * feature() const
Returns the current feature being rendered.
Qgis::GeometryType originalGeometryType() const
Returns the geometry type for the original feature geometry being rendered.
QgsFields fields() const
Fields of the layer.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
qreal opacity() const
Returns the opacity for the symbol.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for all rendered symbols.
qreal opacity() const
Returns the opacity for the symbol.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
Base class for templated line symbols, e.g.
bool rotateSymbols() const
Returns true if the repeating symbols be rotated to match their line segment orientation.
Qgis::RenderUnit outputUnit() const FINAL
Returns the units to use for sizes and widths within the symbol layer.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
static void setCommonProperties(QgsTemplatedLineSymbolLayerBase *destLayer, const QVariantMap &properties)
Sets all common symbol properties in the destLayer, using the settings serialized in the properties m...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
QgsMapUnitScale mapUnitScale() const FINAL
void setMapUnitScale(const QgsMapUnitScale &scale) FINAL
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setIntervalUnit(Qgis::RenderUnit unit)
Sets the units for the interval between symbols.
void setAverageAngleUnit(Qgis::RenderUnit unit)
Sets the unit for the length over which the line's direction is averaged when calculating individual ...
double interval() const
Returns the interval between individual symbols.
void setOffsetAlongLineUnit(Qgis::RenderUnit unit)
Sets the unit used for calculating the offset along line for symbols.
void setAverageAngleMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the length over which the line's direction is averaged when calculating i...
const QgsMapUnitScale & intervalMapUnitScale() const
Returns the map unit scale for the interval between symbols.
double offsetAlongLine() const
Returns the offset along the line for the symbol placement.
~QgsTemplatedLineSymbolLayerBase() override
void copyTemplateSymbolProperties(QgsTemplatedLineSymbolLayerBase *destLayer) const
Copies all common properties of this layer to another templated symbol layer.
Qgis::MarkerLinePlacements placements() const
Returns the placement of the symbols.
void setOffsetAlongLine(double offsetAlongLine)
Sets the the offset along the line for the symbol placement.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) FINAL
Renders the line symbol layer along the outline of polygon, using the given render context.
Qgis::RenderUnit offsetAlongLineUnit() const
Returns the unit used for calculating the offset along line for symbols.
QgsTemplatedLineSymbolLayerBase(bool rotateSymbol=true, double interval=3)
Constructor for QgsTemplatedLineSymbolLayerBase.
virtual void setSymbolLineAngle(double angle)=0
Sets the line angle modification for the symbol's angle.
void setInterval(double interval)
Sets the interval between individual symbols.
Qgis::RenderUnit intervalUnit() const
Returns the units for the interval between symbols.
Q_DECL_DEPRECATED Qgis::MarkerLinePlacement placement() const
Returns the placement of the symbols.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void setPlaceOnEveryPart(bool respect)
Sets whether the placement applies for every part of multi-part feature geometries.
void setPlacements(Qgis::MarkerLinePlacements placements)
Sets the placement of the symbols.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit averageAngleUnit() const
Returns the unit for the length over which the line's direction is averaged when calculating individu...
Q_DECL_DEPRECATED void setPlacement(Qgis::MarkerLinePlacement placement)
Sets the placement of the symbols.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
const QgsMapUnitScale & offsetAlongLineMapUnitScale() const
Returns the map unit scale used for calculating the offset in map units along line for symbols.
virtual void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false)=0
Renders the templated symbol at the specified point, using the given render context.
void setIntervalMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the interval between symbols.
void setOffsetAlongLineMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale used for calculating the offset in map units along line for symbols.
void setAverageAngleLength(double length)
Sets the length of line over which the line's direction is averaged when calculating individual symbo...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Qgis::VectorRenderingSimplificationFlags simplifyHints() const
Gets the simplification hints of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QMap< QString, QString > QgsStringMap
#define DEFAULT_MARKERLINE_INTERVAL
#define DEFAULT_SIMPLELINE_WIDTH
#define DEFAULT_MARKERLINE_ROTATE
#define DEFAULT_SIMPLELINE_PENSTYLE
#define DEFAULT_SIMPLELINE_COLOR
#define QgsDebugMsgLevel(str, level)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
Single variable definition for use within a QgsExpressionContextScope.
Utility class for identifying a unique vertex within a geometry.
Qgis::VertexType type
Vertex type.