47#include <QDomDocument>
52using namespace Qt::StringLiterals;
59 mCustomDashVector << 5 << 2;
69 mCustomDashPatternUnit = unit;
70 mDashPatternOffsetUnit = unit;
71 mTrimDistanceStartUnit = unit;
72 mTrimDistanceEndUnit = unit;
96 mCustomDashPatternMapUnitScale = scale;
116 if ( props.contains( u
"line_color"_s ) )
120 else if ( props.contains( u
"outline_color"_s ) )
124 else if ( props.contains( u
"color"_s ) )
129 if ( props.contains( u
"line_width"_s ) )
131 width = props[u
"line_width"_s].toDouble();
133 else if ( props.contains( u
"outline_width"_s ) )
135 width = props[u
"outline_width"_s].toDouble();
137 else if ( props.contains( u
"width"_s ) )
140 width = props[u
"width"_s].toDouble();
142 if ( props.contains( u
"line_style"_s ) )
146 else if ( props.contains( u
"outline_style"_s ) )
150 else if ( props.contains( u
"penstyle"_s ) )
156 if ( props.contains( u
"line_width_unit"_s ) )
160 else if ( props.contains( u
"outline_width_unit"_s ) )
164 else if ( props.contains( u
"width_unit"_s ) )
169 if ( props.contains( u
"width_map_unit_scale"_s ) )
171 if ( props.contains( u
"offset"_s ) )
172 l->
setOffset( props[u
"offset"_s].toDouble() );
173 if ( props.contains( u
"offset_unit"_s ) )
175 if ( props.contains( u
"offset_map_unit_scale"_s ) )
177 if ( props.contains( u
"joinstyle"_s ) )
179 if ( props.contains( u
"capstyle"_s ) )
182 if ( props.contains( u
"use_custom_dash"_s ) )
186 if ( props.contains( u
"customdash"_s ) )
190 if ( props.contains( u
"customdash_unit"_s ) )
194 if ( props.contains( u
"customdash_map_unit_scale"_s ) )
199 if ( props.contains( u
"draw_inside_polygon"_s ) )
204 if ( props.contains( u
"ring_filter"_s ) )
209 if ( props.contains( u
"dash_pattern_offset"_s ) )
211 if ( props.contains( u
"dash_pattern_offset_unit"_s ) )
213 if ( props.contains( u
"dash_pattern_offset_map_unit_scale"_s ) )
216 if ( props.contains( u
"trim_distance_start"_s ) )
218 if ( props.contains( u
"trim_distance_start_unit"_s ) )
220 if ( props.contains( u
"trim_distance_start_map_unit_scale"_s ) )
222 if ( props.contains( u
"trim_distance_end"_s ) )
224 if ( props.contains( u
"trim_distance_end_unit"_s ) )
226 if ( props.contains( u
"trim_distance_end_map_unit_scale"_s ) )
229 if ( props.contains( u
"align_dash_pattern"_s ) )
232 if ( props.contains( u
"tweak_dash_pattern_on_corners"_s ) )
242 return u
"SimpleLine"_s;
254 mPen.setColor( penColor );
256 mPen.setWidthF( scaledWidth );
260 const double dashWidthDiv = std::max( 1.0, scaledWidth );
261 if ( mUseCustomDashPattern )
263 mPen.setStyle( Qt::CustomDashLine );
267 QVector<qreal> scaledVector;
268 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
269 for ( ; it != mCustomDashVector.constEnd(); ++it )
274 mPen.setDashPattern( scaledVector );
278 mPen.setStyle( mPenStyle );
281 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
286 mPen.setJoinStyle( mPenJoinStyle );
287 mPen.setCapStyle( mPenCapStyle );
292 selColor.setAlphaF( context.
opacity() );
293 mSelPen.setColor( selColor );
310 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
317 if ( mDrawInsidePolygon )
325 if ( mDrawInsidePolygon )
328 QPainterPath clipPath;
329 clipPath.addPolygon( points );
334 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
336 QPolygonF ring = *it;
337 clipPath.addPolygon( ring );
342 p->setClipPath( clipPath, Qt::IntersectClip );
365 for (
const QPolygonF &ring : std::as_const( *rings ) )
381 if ( mDrawInsidePolygon )
397 QPolygonF points = pts;
399 double startTrim = mTrimDistanceStart;
405 double endTrim = mTrimDistanceEnd;
412 double totalLength = -1;
416 startTrim = startTrim * 0.01 * totalLength;
424 if ( totalLength < 0 )
426 endTrim = endTrim * 0.01 * totalLength;
439 mPen.setColor( penColor );
442 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
445 const QPen pen = useSelectedColor ? mSelPen : mPen;
447 if ( !pen.dashPattern().isEmpty() )
450 const QVector<double> pattern = pen.dashPattern();
451 bool foundNonNull =
false;
452 for (
int i = 0; i < pattern.size(); ++i )
464 p->setBrush( Qt::NoBrush );
467 std::unique_ptr< QgsScopedQPainterState > painterState;
468 if ( points.size() <= 2 &&
471 ( p->renderHints() & QPainter::Antialiasing ) )
473 painterState = std::make_unique< QgsScopedQPainterState >( p );
474 p->setRenderHint( QPainter::Antialiasing,
false );
477 const bool applyPatternTweaks = mAlignDashPattern
478 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
479 && pen.dashOffset() == 0;
483 if ( applyPatternTweaks )
485 drawPathWithDashPatternTweaks( p, points, pen );
491 path.addPolygon( points );
506 for (
const QPolygonF &part : mline )
508 if ( applyPatternTweaks )
510 drawPathWithDashPatternTweaks( p, part, pen );
516 path.addPolygon( part );
527 map[u
"line_width"_s] = QString::number(
mWidth );
533 map[u
"offset"_s] = QString::number(
mOffset );
536 map[u
"use_custom_dash"_s] = ( mUseCustomDashPattern ? u
"1"_s : u
"0"_s );
540 map[u
"dash_pattern_offset"_s] = QString::number( mDashPatternOffset );
543 map[u
"trim_distance_start"_s] = QString::number( mTrimDistanceStart );
546 map[u
"trim_distance_end"_s] = QString::number( mTrimDistanceEnd );
549 map[u
"draw_inside_polygon"_s] = ( mDrawInsidePolygon ? u
"1"_s : u
"0"_s );
550 map[u
"ring_filter"_s] = QString::number(
static_cast< int >(
mRingFilter ) );
551 map[u
"align_dash_pattern"_s] = mAlignDashPattern ? u
"1"_s : u
"0"_s;
552 map[u
"tweak_dash_pattern_on_corners"_s] = mPatternCartographicTweakOnSharpCorners ? u
"1"_s : u
"0"_s;
593 toSld( doc, element, context );
598 if ( mPenStyle == Qt::NoPen )
602 QDomElement symbolizerElem = doc.createElement( u
"se:LineSymbolizer"_s );
603 if ( !props.value( u
"uom"_s, QString() ).toString().isEmpty() )
604 symbolizerElem.setAttribute( u
"uom"_s, props.value( u
"uom"_s, QString() ).toString() );
605 element.appendChild( symbolizerElem );
611 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
612 symbolizerElem.appendChild( strokeElem );
614 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
623 QDomElement perpOffsetElem = doc.createElement( u
"se:PerpendicularOffset"_s );
626 symbolizerElem.appendChild( perpOffsetElem );
633 if ( mUseCustomDashPattern )
636 mPen.color(), mPenJoinStyle,
637 mPenCapStyle,
mOffset, &mCustomDashVector );
650 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
651 if ( strokeElem.isNull() )
668 QDomElement perpOffsetElem = element.firstChildElement( u
"PerpendicularOffset"_s );
669 if ( !perpOffsetElem.isNull() )
672 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
677 double scaleFactor = 1.0;
678 const QString uom = element.attribute( u
"uom"_s );
693void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
699 bool hasStrokeWidthExpression =
false;
706 pen.setWidthF( scaledWidth );
707 selPen.setWidthF( scaledWidth );
708 hasStrokeWidthExpression =
true;
717 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
718 pen.setColor( penColor );
732 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
737 const QStringList dashList = customDashString.split(
';' );
738 QVector<qreal> dashVector;
739 for (
const QString &dash : dashList )
743 pen.setDashPattern( dashVector );
749 QVector<qreal> scaledVector;
750 for (
double v : std::as_const( mCustomDashVector ) )
755 mPen.setDashPattern( scaledVector );
759 double patternOffset = mDashPatternOffset;
792void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
794 if ( pen.dashPattern().empty() || points.size() < 2 )
797 if ( pen.widthF() <= 1.0 )
799 pen.setWidthF( 1.0001 );
802 QVector< qreal > sourcePattern = pen.dashPattern();
803 const double dashWidthDiv = pen.widthF();
805 for (
int i = 0; i < sourcePattern.size(); ++ i )
806 sourcePattern[i] *= pen.widthF();
808 QVector< qreal > buffer;
809 QPolygonF bufferedPoints;
810 QPolygonF previousSegmentBuffer;
815 auto ptIt = points.constBegin();
816 double totalBufferLength = 0;
817 int patternIndex = 0;
818 double currentRemainingDashLength = 0;
819 double currentRemainingGapLength = 0;
821 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
823 QVector< qreal > result;
824 result.reserve( buffer.size() );
825 for (
auto it = buffer.begin(); it != buffer.end(); )
829 while ( dash == 0 && !result.empty() )
831 result.last() += gap;
833 if ( it == buffer.end() )
838 while ( gap == 0 && it != buffer.end() )
843 result << dash << gap;
848 double currentBufferLineLength = 0;
849 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
850 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
852 if ( buffer.empty() || bufferedPoints.size() < 2 )
857 if ( currentRemainingDashLength )
860 buffer << currentRemainingDashLength << 0.0;
861 totalBufferLength += currentRemainingDashLength;
863 QVector< qreal > compressed = compressPattern( buffer );
864 if ( !currentRemainingDashLength )
867 totalBufferLength -= compressed.last();
868 compressed.last() = 0;
872 const double scaleFactor = currentBufferLineLength / totalBufferLength;
874 bool shouldFlushPreviousSegmentBuffer =
false;
876 if ( !previousSegmentBuffer.empty() )
880 if ( !firstDashSubstring.empty() )
886 compressed = compressed.mid( 2 );
887 shouldFlushPreviousSegmentBuffer = !compressed.empty();
890 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
892 QPen adjustedPen = pen;
893 adjustedPen.setStyle( Qt::SolidLine );
894 painter->setPen( adjustedPen );
896 path.addPolygon( previousSegmentBuffer );
897 painter->drawPath( path );
898 previousSegmentBuffer.clear();
901 double finalDash = 0;
908 if ( !compressed.empty() )
910 finalDash = compressed.at( compressed.size() - 2 );
911 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
913 const QPolygonF thisPoints = bufferedPoints;
919 previousSegmentBuffer << bufferedPoints;
923 currentBufferLineLength = 0;
924 currentRemainingDashLength = 0;
925 currentRemainingGapLength = 0;
926 totalBufferLength = 0;
929 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
931 QPen adjustedPen = pen;
932 if ( !compressed.empty() )
935 compressed = compressed.mid( 0, 32 );
936 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
937 adjustedPen.setDashPattern( compressed );
941 adjustedPen.setStyle( Qt::SolidLine );
944 painter->setPen( adjustedPen );
946 path.addPolygon( bufferedPoints );
947 painter->drawPath( path );
950 bufferedPoints.clear();
956 bufferedPoints << p2;
957 for ( ; ptIt != points.constEnd(); ++ptIt )
965 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
966 currentBufferLineLength += remainingSegmentDistance;
970 if ( currentRemainingDashLength > 0 )
973 if ( remainingSegmentDistance >= currentRemainingDashLength )
976 buffer << currentRemainingDashLength << 0.0;
977 totalBufferLength += currentRemainingDashLength;
978 remainingSegmentDistance -= currentRemainingDashLength;
980 currentRemainingDashLength = 0.0;
981 currentRemainingGapLength = sourcePattern.at( patternIndex );
982 if ( currentRemainingGapLength == 0.0 )
990 buffer << remainingSegmentDistance << 0.0;
991 totalBufferLength += remainingSegmentDistance;
992 currentRemainingDashLength -= remainingSegmentDistance;
996 if ( currentRemainingGapLength > 0 )
999 if ( remainingSegmentDistance >= currentRemainingGapLength )
1002 buffer << 0.0 << currentRemainingGapLength;
1003 totalBufferLength += currentRemainingGapLength;
1004 remainingSegmentDistance -= currentRemainingGapLength;
1005 currentRemainingGapLength = 0.0;
1011 buffer << 0.0 << remainingSegmentDistance;
1012 totalBufferLength += remainingSegmentDistance;
1013 currentRemainingGapLength -= remainingSegmentDistance;
1018 if ( patternIndex + 1 >= sourcePattern.size() )
1023 const double nextPatternDashLength = sourcePattern.at( patternIndex );
1024 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
1025 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1027 buffer << nextPatternDashLength << nextPatternGapLength;
1028 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1029 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1032 else if ( nextPatternDashLength <= remainingSegmentDistance )
1035 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1036 totalBufferLength += remainingSegmentDistance;
1037 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1038 currentRemainingDashLength = 0;
1045 buffer << remainingSegmentDistance << 0.0;
1046 totalBufferLength += remainingSegmentDistance;
1047 currentRemainingGapLength = 0;
1048 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1053 bufferedPoints << p1;
1054 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1056 QPointF nextPoint = *( ptIt + 1 );
1062 flushBuffer( &nextPoint );
1063 bufferedPoints << p1;
1066 if ( patternIndex % 2 == 1 )
1070 currentRemainingDashLength = sourcePattern.at( patternIndex );
1077 flushBuffer(
nullptr );
1078 if ( !previousSegmentBuffer.empty() )
1080 QPen adjustedPen = pen;
1081 adjustedPen.setStyle( Qt::SolidLine );
1082 painter->setPen( adjustedPen );
1084 path.addPolygon( previousSegmentBuffer );
1085 painter->drawPath( path );
1086 previousSegmentBuffer.clear();
1092 if ( mDrawInsidePolygon )
1106 unit = mCustomDashPatternUnit;
1107 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1144 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1149 return mAlignDashPattern;
1159 return mPatternCartographicTweakOnSharpCorners;
1164 mPatternCartographicTweakOnSharpCorners =
enabled;
1189 : mRotateSymbols( rotateSymbol )
1229 if ( mRenderingFeature )
1233 mFeatureSymbolOpacity = context.
opacity();
1234 mCurrentFeatureIsSelected = useSelectedColor;
1252 QString placementString = exprVal.toString();
1253 if ( placementString.compare(
"interval"_L1, Qt::CaseInsensitive ) == 0 )
1257 else if ( placementString.compare(
"vertex"_L1, Qt::CaseInsensitive ) == 0 )
1261 else if ( placementString.compare(
"innervertices"_L1, Qt::CaseInsensitive ) == 0 )
1265 else if ( placementString.compare(
"lastvertex"_L1, Qt::CaseInsensitive ) == 0 )
1269 else if ( placementString.compare(
"firstvertex"_L1, Qt::CaseInsensitive ) == 0 )
1273 else if ( placementString.compare(
"centerpoint"_L1, Qt::CaseInsensitive ) == 0 )
1277 else if ( placementString.compare(
"curvepoint"_L1, Qt::CaseInsensitive ) == 0 )
1281 else if ( placementString.compare(
"segmentcenter"_L1, Qt::CaseInsensitive ) == 0 )
1294 double averageOver = mAverageAngleLength;
1309 if ( !error.isEmpty() )
1311 QgsDebugError( u
"Badly formatted blank segment '%1', skip it: %2"_s.arg( strBlankSegments ).arg( error ) );
1317 if ( iPart >= 0 &&
mRingIndex >= 0 && iPart < allBlankSegments.count() &&
mRingIndex < allBlankSegments.at( iPart ).count() )
1319 blankSegments = allBlankSegments.at( iPart ).at(
mRingIndex );
1327 renderPolylineInterval( points, context, averageOver, blankSegments );
1329 renderPolylineCentral( points, context, averageOver, blankSegments );
1333 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1336 mHasRenderedFirstPart = mRenderingFeature;
1352 for (
int part = 0; part < mline.count(); ++part )
1354 const QPolygonF &points2 = mline[ part ];
1357 renderPolylineInterval( points2, context, averageOver, blankSegments );
1359 renderPolylineCentral( points2, context, averageOver, blankSegments );
1367 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1370 mHasRenderedFirstPart = mRenderingFeature;
1390 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1420 for (
int i = 0; i < rings->size(); ++i )
1455 mIntervalUnit = unit;
1456 mOffsetAlongLineUnit = unit;
1457 mAverageAngleLengthUnit = unit;
1483 map[u
"interval"_s] = QString::number(
interval() );
1484 map[u
"offset"_s] = QString::number(
mOffset );
1492 map[u
"average_angle_length"_s] = QString::number( mAverageAngleLength );
1499 map[u
"ring_filter"_s] = QString::number(
static_cast< int >(
mRingFilter ) );
1500 map[u
"place_on_every_part"_s] = mPlaceOnEveryPart;
1506 return mPlaceOnEveryPart
1516 mRenderingFeature =
true;
1517 mHasRenderedFirstPart =
false;
1522 mRenderingFeature =
false;
1533 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1534 mFeatureSymbolOpacity = 1;
1569 if (
properties.contains( u
"offset_unit"_s ) )
1573 if (
properties.contains( u
"interval_unit"_s ) )
1577 if (
properties.contains( u
"offset_along_line"_s ) )
1581 if (
properties.contains( u
"offset_along_line_unit"_s ) )
1585 if (
properties.contains( ( u
"offset_along_line_map_unit_scale"_s ) ) )
1590 if (
properties.contains( u
"offset_map_unit_scale"_s ) )
1594 if (
properties.contains( u
"interval_map_unit_scale"_s ) )
1599 if (
properties.contains( u
"average_angle_length"_s ) )
1603 if (
properties.contains( u
"average_angle_unit"_s ) )
1607 if (
properties.contains( ( u
"average_angle_map_unit_scale"_s ) ) )
1611 if (
properties.contains( u
"blank_segments_unit"_s ) )
1618 if (
properties[u
"placement"_s] ==
"vertex"_L1 )
1620 else if (
properties[u
"placement"_s] ==
"lastvertex"_L1 )
1622 else if (
properties[u
"placement"_s] ==
"firstvertex"_L1 )
1624 else if (
properties[u
"placement"_s] ==
"centralpoint"_L1 )
1626 else if (
properties[u
"placement"_s] ==
"curvepoint"_L1 )
1628 else if (
properties[u
"placement"_s] ==
"segmentcenter"_L1 )
1633 else if (
properties.contains( u
"placements"_s ) )
1639 if (
properties.contains( u
"ring_filter"_s ) )
1655class BlankSegmentsWalker
1660 : mBlankSegments( blankSegments )
1662 , mItBlankSegment( blankSegments.cbegin() )
1664 mDistances.reserve( mPoints.count() );
1668 bool insideBlankSegment(
double distance )
1670 while ( mItBlankSegment != mBlankSegments.cend() && distance > mItBlankSegment->second )
1675 return ( mItBlankSegment != mBlankSegments.cend() && distance >= mItBlankSegment->first );
1680 bool insideBlankSegment(
const QPointF &point,
int pointIndex )
1682 if ( pointIndex < 0 || pointIndex >= mPoints.count() )
1686 if ( pointIndex >= mDistances.count() )
1688 for (
int i =
static_cast<int>( mDistances.count() ); i < pointIndex + 1; i++ )
1690 const QPointF diff = mPoints.at( i ) - mPoints.at( i - 1 );
1691 const double distance = std::sqrt( std::pow( diff.x(), 2 ) + std::pow( diff.y(), 2 ) );
1692 const double totalDistance = distance + mDistances.last();
1693 mDistances << totalDistance;
1697 const QPointF diff = mPoints.at( pointIndex ) - point;
1698 const double distance = std::sqrt( std::pow( diff.x(), 2 ) + std::pow( diff.y(), 2 ) );
1699 const double currentDistance = mDistances.at( pointIndex ) + distance;
1701 return insideBlankSegment( currentDistance );
1707 const QPolygonF &mPoints;
1708 QList<double> mDistances;
1709 QgsBlankSegmentUtils::BlankSegments::const_iterator mItBlankSegment;
1718 if ( points.isEmpty() )
1722 double lengthLeft = 0;
1727 QgsExpressionContextScope *scope =
new QgsExpressionContextScope();
1754 constexpr double EPSILON = 1e-5;
1755 if ( painterUnitInterval <
EPSILON )
1758 double painterUnitOffsetAlongLine = 0;
1761 double totalLength = -1;
1782 if ( points.isClosed() )
1784 if ( painterUnitOffsetAlongLine > 0 )
1786 if ( totalLength < 0 )
1788 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1790 else if ( painterUnitOffsetAlongLine < 0 )
1792 if ( totalLength < 0 )
1794 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1806 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1808 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1810 QVector< QPointF > angleStartPoints;
1811 QVector< QPointF > symbolPoints;
1812 QVector< QPointF > angleEndPoints;
1821 QList<int> pointIndices;
1822 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft, blankSegments.isEmpty() ?
nullptr : &pointIndices );
1824 if ( symbolPoints.empty() )
1830 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1833 symbolPoints.pop_back();
1836 angleEndPoints.reserve( symbolPoints.size() );
1837 angleStartPoints.reserve( symbolPoints.size() );
1838 if ( averageOver <= painterUnitOffsetAlongLine )
1840 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver,
nullptr, 0, symbolPoints.size() );
1844 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0,
nullptr, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1846 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver,
nullptr, 0, symbolPoints.size() );
1849 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
1850 for (
int i = 0; i < symbolPoints.size(); ++ i )
1855 const QPointF pt = symbolPoints[i];
1856 if ( i < pointIndices.count() && blankSegmentsWalker.insideBlankSegment( pt, pointIndices.at( i ) ) )
1860 const QPointF startPt = angleStartPoints[i];
1861 const QPointF endPt = angleEndPoints[i];
1863 Line l( startPt, endPt );
1879 QPointF lastPt = points[0];
1880 BlankSegmentsWalker itBlankSegment( points, blankSegments );
1881 for (
int i = 1; i < points.count(); ++i )
1886 const QPointF &pt = points[i];
1892 Line l( lastPt, pt );
1893 QPointF diff = l.diffForInterval( painterUnitInterval );
1898 double c = 1 - lengthLeft / painterUnitInterval;
1900 lengthLeft += l.length();
1909 while ( lengthLeft > painterUnitInterval )
1916 if ( !itBlankSegment.insideBlankSegment( lastPt, i - 1 ) )
1922 lengthLeft -= painterUnitInterval;
1931static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1934 double a1 = Line( prevPt, pt ).angle();
1935 double a2 = Line( pt, nextPt ).angle();
1936 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1938 return std::atan2( unitY, unitX );
1943 if ( points.isEmpty() )
1948 int i = -1, maxCount = 0;
1949 bool isRing =
false;
1951 QgsExpressionContextScope *scope =
new QgsExpressionContextScope();
1963 double totalLength = -1;
1983 if ( points.isClosed() )
1987 if ( totalLength < 0 )
1993 if ( totalLength < 0 )
2067 i = points.count() - 1;
2069 maxCount = points.count();
2077 maxCount = points.count() - 1;
2085 maxCount = points.count();
2086 if ( points.first() == points.last() )
2103 renderOffsetVertexAlongLine( points, i, distance, context,
placement, blankSegments );
2110 prevPoint = points.at( 0 );
2112 QPointF symbolPoint;
2113 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
2114 for ( ; i < maxCount; ++i )
2125 QPointF currentPoint = points.at( i );
2126 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2127 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2130 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2131 currentPoint.x() - prevPoint.x() );
2134 prevPoint = currentPoint;
2138 symbolPoint = points.at( i );
2142 double angle = markerAngle( points, isRing, i );
2147 mFinalVertex = symbolPoint;
2149 && !blankSegmentsWalker.insideBlankSegment( symbolPoint, i ) )
2154double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2157 const QPointF &pt = points[vertex];
2159 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2161 int prevIndex = vertex - 1;
2162 int nextIndex = vertex + 1;
2164 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2166 prevIndex = points.count() - 2;
2170 QPointF prevPoint, nextPoint;
2171 while ( prevIndex >= 0 )
2173 prevPoint = points[ prevIndex ];
2174 if ( prevPoint != pt )
2181 while ( nextIndex < points.count() )
2183 nextPoint = points[ nextIndex ];
2184 if ( nextPoint != pt )
2191 if ( prevIndex >= 0 && nextIndex < points.count() )
2193 angle = _averageAngle( prevPoint, pt, nextPoint );
2200 while ( vertex < points.size() - 1 )
2202 const QPointF &nextPt = points[vertex + 1];
2205 angle = Line( pt, nextPt ).angle();
2214 while ( vertex >= 1 )
2216 const QPointF &prevPt = points[vertex - 1];
2219 angle = Line( prevPt, pt ).angle();
2231 if ( points.isEmpty() )
2241 bool isRing =
false;
2242 if ( points.first() == points.last() )
2244 double angle = markerAngle( points, isRing, vertex );
2247 mFinalVertex = points[vertex];
2253 int pointIncrement = distance > 0 ? 1 : -1;
2254 QPointF previousPoint = points[vertex];
2255 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2256 int endPoint = distance > 0 ? points.count() - 1 : 0;
2257 double distanceLeft = std::fabs( distance );
2258 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
2260 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2262 const QPointF &pt = points[i];
2264 if ( previousPoint == pt )
2268 Line l( previousPoint, pt );
2270 if ( distanceLeft < l.length() )
2273 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2279 mFinalVertex = markerPoint;
2281 && !blankSegmentsWalker.insideBlankSegment( markerPoint, i - 1 ) )
2286 distanceLeft -= l.length();
2293void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
2294 QList<int> *pointIndices,
2295 double initialLag,
int numberPointsRequired )
2300 QVector< QPointF > points = p;
2301 const bool closedRing = points.first() == points.last();
2303 double lengthLeft = initialOffset;
2305 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2306 if ( initialLagLeft < 0 && closedRing )
2309 QPointF lastPt = points.constLast();
2310 QVector< QPointF > pseudoPoints;
2311 for (
int i = points.count() - 2; i > 0; --i )
2313 if ( initialLagLeft >= 0 )
2318 const QPointF &pt = points[i];
2323 Line l( lastPt, pt );
2324 initialLagLeft += l.length();
2329 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2331 points = pseudoPoints;
2336 while ( initialLagLeft < 0 )
2338 dest << points.constFirst();
2339 initialLagLeft += intervalPainterUnits;
2342 if ( initialLag > 0 )
2344 lengthLeft += intervalPainterUnits - initialLagLeft;
2347 QPointF lastPt = points[0];
2348 for (
int i = 1; i < points.count(); ++i )
2350 const QPointF &pt = points[i];
2354 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2363 Line l( lastPt, pt );
2364 QPointF diff = l.diffForInterval( intervalPainterUnits );
2368 double c = 1 - lengthLeft / intervalPainterUnits;
2370 lengthLeft += l.length();
2373 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2377 lengthLeft -= intervalPainterUnits;
2380 *pointIndices << i - 1;
2383 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2388 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2392 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2399 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2402 while ( dest.size() < numberPointsRequired )
2403 dest << points.constLast();
2409 if ( !points.isEmpty() )
2413 QPolygonF::const_iterator it = points.constBegin();
2415 for ( ++it; it != points.constEnd(); ++it )
2417 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2418 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2424 const double midPoint = length / 2;
2426 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
2427 if ( blankSegmentsWalker.insideBlankSegment( midPoint ) )
2431 double thisSymbolAngle = 0;
2433 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2435 QVector< QPointF > angleStartPoints;
2436 QVector< QPointF > symbolPoints;
2437 QVector< QPointF > angleEndPoints;
2441 collectOffsetPoints( points, symbolPoints, midPoint, midPoint,
nullptr, 0.0, 2 );
2442 collectOffsetPoints( points, angleStartPoints, midPoint, 0,
nullptr, averageAngleOver, 2 );
2443 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver,
nullptr, 0, 2 );
2445 pt = symbolPoints.at( 1 );
2446 Line l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2447 thisSymbolAngle = l.angle();
2452 it = points.constBegin();
2454 qreal last_at = 0, next_at = 0;
2456 for ( ++it; it != points.constEnd(); ++it )
2459 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2460 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2461 if ( next_at >= midPoint )
2468 Line l( last, next );
2469 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2470 pt = last + ( next - last ) * k;
2471 thisSymbolAngle = l.angle();
2523 if ( props.contains( u
"interval"_s ) )
2524 interval = props[u
"interval"_s].toDouble();
2525 if ( props.contains( u
"rotate"_s ) )
2526 rotate = ( props[u
"rotate"_s].toString() ==
"1"_L1 );
2528 auto x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2535 return u
"MarkerLine"_s;
2555 mMarker->setRenderHints( hints );
2577 toSld( doc, element, context );
2583 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2585 QDomElement symbolizerElem = doc.createElement( u
"se:LineSymbolizer"_s );
2586 if ( !props.value( u
"uom"_s, QString() ).toString().isEmpty() )
2587 symbolizerElem.setAttribute( u
"uom"_s, props.value( u
"uom"_s, QString() ).toString() );
2588 element.appendChild( symbolizerElem );
2618 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
2619 symbolizerElem.appendChild( strokeElem );
2622 QDomElement graphicStrokeElem = doc.createElement( u
"se:GraphicStroke"_s );
2623 strokeElem.appendChild( graphicStrokeElem );
2628 markerLayer->writeSldMarker( doc, graphicStrokeElem, context );
2636 QgsDebugError( u
"Missing marker line symbol layer. Skip it."_s );
2639 if ( !gap.isEmpty() )
2641 QDomElement gapElem = doc.createElement( u
"se:Gap"_s );
2643 graphicStrokeElem.appendChild( gapElem );
2648 QDomElement perpOffsetElem = doc.createElement( u
"se:PerpendicularOffset"_s );
2651 symbolizerElem.appendChild( perpOffsetElem );
2661 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
2662 if ( strokeElem.isNull() )
2665 QDomElement graphicStrokeElem = strokeElem.firstChildElement( u
"GraphicStroke"_s );
2666 if ( graphicStrokeElem.isNull() )
2674 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2676 if ( it.key() ==
"placement"_L1 )
2678 if ( it.value() ==
"points"_L1 )
2680 else if ( it.value() ==
"firstPoint"_L1 )
2682 else if ( it.value() ==
"lastPoint"_L1 )
2684 else if ( it.value() ==
"centralPoint"_L1 )
2687 else if ( it.value() ==
"rotateMarker"_L1 )
2693 std::unique_ptr< QgsMarkerSymbol > marker;
2699 layers.append( l.release() );
2700 marker = std::make_unique<QgsMarkerSymbol>( layers );
2707 QDomElement gapElem = graphicStrokeElem.firstChildElement( u
"Gap"_s );
2708 if ( !gapElem.isNull() )
2711 double d = gapElem.firstChild().firstChild().nodeValue().toDouble( &ok );
2717 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( u
"PerpendicularOffset"_s );
2718 if ( !perpOffsetElem.isNull() )
2721 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2726 double scaleFactor = 1.0;
2727 const QString uom = element.attribute( u
"uom"_s );
2750 mMarker->setDataDefinedSize( property );
2757 const double prevOpacity =
mMarker->opacity();
2760 mMarker->setOpacity( prevOpacity );
2765 mMarker->setLineAngle( angle );
2783 mMarker->renderPoint( point, feature, context, layer, selected );
2795 return mMarker->size( context );
2801 mMarker->setOutputUnit( unit );
2819 attr.unite(
mMarker->usedAttributes( context ) );
2834 return (
mMarker->size( context ) / 2.0 ) +
2856 if ( props.contains( u
"interval"_s ) )
2857 interval = props[u
"interval"_s].toDouble();
2858 if ( props.contains( u
"rotate"_s ) )
2859 rotate = ( props[u
"rotate"_s] ==
"1"_L1 );
2861 auto x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2863 if ( props.contains( u
"hash_angle"_s ) )
2865 x->setHashAngle( props[u
"hash_angle"_s].toDouble() );
2868 if ( props.contains( u
"hash_length"_s ) )
2869 x->setHashLength( props[u
"hash_length"_s].toDouble() );
2871 if ( props.contains( u
"hash_length_unit"_s ) )
2874 if ( props.contains( u
"hash_length_map_unit_scale"_s ) )
2882 return u
"HashLine"_s;
2891 mHashSymbol->setRenderHints( hints );
2904 map[ u
"hash_angle"_s ] = QString::number( mHashAngle );
2906 map[u
"hash_length"_s] = QString::number( mHashLength );
2917 x->setHashAngle( mHashAngle );
2918 x->setHashLength( mHashLength );
2919 x->setHashLengthUnit( mHashLengthUnit );
2920 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2926 mHashSymbol->setColor(
color );
2932 return mHashSymbol ? mHashSymbol->color() :
mColor;
2937 return mHashSymbol.get();
2948 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2949 mColor = mHashSymbol->color();
2955 mHashLength =
width;
2970 return ( mHashSymbol->width( context ) / 2.0 )
2978 mHashSymbol->setOutputUnit( unit );
2985 attr.unite( mHashSymbol->usedAttributes( context ) );
2993 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
3002 mHashSymbol->setDataDefinedWidth( property );
3016 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
3021 mSymbolLineAngle = angle;
3026 return mSymbolAngle;
3031 mSymbolAngle = angle;
3036 double lineLength = mHashLength;
3042 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
3056 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
3061 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
3078 const double prevOpacity = mHashSymbol->opacity();
3079 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
3081 mHashSymbol->setOpacity( prevOpacity );
3100 QPolygonF offsetPoints;
3103 renderLine( points, context, patternThickness, patternLength, brush );
3112 renderLine( part, context, patternThickness, patternLength, brush );
3117void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3118 const double patternLength,
const QBrush &sourceBrush )
3124 QBrush brush = sourceBrush;
3129 QPolygonF inputPoints;
3130 inputPoints.reserve( points.size() );
3132 double minX = std::numeric_limits< double >::max();
3133 double minY = std::numeric_limits< double >::max();
3134 double maxX = std::numeric_limits< double >::lowest();
3135 double maxY = std::numeric_limits< double >::lowest();
3137 for (
const QPointF &pt : std::as_const( points ) )
3144 minX = std::min( minX, pt.x() );
3145 minY = std::min( minY, pt.y() );
3146 maxX = std::max( maxX, pt.x() );
3147 maxY = std::max( maxY, pt.y() );
3150 if ( inputPoints.size() < 2 )
3154 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3156 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3159 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3160 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3162 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3163 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3165 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3166 if ( temporaryImage.isNull() )
3175 temporaryImage.fill( Qt::transparent );
3198 QPainterPathStroker stroker;
3199 stroker.setWidth( lineThickness );
3200 stroker.setCapStyle( cap );
3201 stroker.setJoinStyle( join );
3204 path.addPolygon( inputPoints );
3205 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3208 QPainter imagePainter;
3209 imagePainter.begin( &temporaryImage );
3211 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3213 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3214 imagePainter.setPen( Qt::NoPen );
3216 QPointF segmentStartPoint = inputPoints.at( 0 );
3219 double progressThroughImage = 0;
3221 QgsPoint prevSegmentPolygonEndLeft;
3222 QgsPoint prevSegmentPolygonEndRight;
3225 QgsPoint startLinePolygonLeft;
3226 QgsPoint startLinePolygonRight;
3228 for (
int i = 1; i < inputPoints.size(); ++i )
3233 const QPointF segmentEndPoint = inputPoints.at( i );
3235 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3238 QgsPoint thisSegmentPolygonEndLeft;
3239 QgsPoint thisSegmentPolygonEndRight;
3241 QgsPoint thisSegmentPolygonEndLeftForPainter;
3242 QgsPoint thisSegmentPolygonEndRightForPainter;
3250 const QgsPoint startPointLeft = QgsPoint( segmentStartPoint ).project( lineThickness / 2, segmentAngleDegrees );
3251 const QgsPoint endPointLeft = QgsPoint( segmentEndPoint ).project( lineThickness / 2, segmentAngleDegrees );
3252 const QgsPoint startPointRight = QgsPoint( segmentStartPoint ).project( -lineThickness / 2, segmentAngleDegrees );
3253 const QgsPoint endPointRight = QgsPoint( segmentEndPoint ).project( -lineThickness / 2, segmentAngleDegrees );
3257 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtilsBase::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3258 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3261 const QgsPoint lastSegmentStartPointLeft = QgsPoint( points.at( points.size() - 2 ) ).project( lineThickness / 2, lastSegmentAngleDegrees );
3262 const QgsPoint lastSegmentEndPointLeft = QgsPoint( segmentStartPoint ).project( lineThickness / 2, lastSegmentAngleDegrees );
3263 const QgsPoint lastSegmentStartPointRight = QgsPoint( points.at( points.size() - 2 ) ).project( -lineThickness / 2, lastSegmentAngleDegrees );
3264 const QgsPoint lastSegmentEndPointRight = QgsPoint( segmentStartPoint ).project( -lineThickness / 2, lastSegmentAngleDegrees );
3269 QgsPoint intersectionPoint;
3270 bool isIntersection =
false;
3272 if ( !isIntersection )
3273 prevSegmentPolygonEndLeft = startPointLeft;
3274 isIntersection =
false;
3275 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3276 if ( !isIntersection )
3277 prevSegmentPolygonEndRight = startPointRight;
3279 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3280 startLinePolygonRight = prevSegmentPolygonEndRight;
3284 prevSegmentPolygonEndLeft = QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3285 if ( cap != Qt::PenCapStyle::FlatCap )
3286 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3287 prevSegmentPolygonEndRight = QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3288 if ( cap != Qt::PenCapStyle::FlatCap )
3289 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3293 if ( i < inputPoints.size() - 1 )
3298 const QgsPoint startPointLeft = QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3299 const QgsPoint endPointLeft = QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3300 const QgsPoint startPointRight = QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3301 const QgsPoint endPointRight = QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3306 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3309 const QgsPoint nextSegmentStartPointLeft = QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3310 const QgsPoint nextSegmentEndPointLeft = QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3311 const QgsPoint nextSegmentStartPointRight = QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3312 const QgsPoint nextSegmentEndPointRight = QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3317 QgsPoint intersectionPoint;
3318 bool isIntersection =
false;
3320 if ( !isIntersection )
3321 thisSegmentPolygonEndLeft = endPointLeft;
3322 isIntersection =
false;
3323 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3324 if ( !isIntersection )
3325 thisSegmentPolygonEndRight = endPointRight;
3327 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3328 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3336 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3337 thisSegmentPolygonEndRight = startLinePolygonRight;
3339 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3340 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3344 thisSegmentPolygonEndLeft = QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3345 if ( cap != Qt::PenCapStyle::FlatCap )
3346 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3347 thisSegmentPolygonEndRight = QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3348 if ( cap != Qt::PenCapStyle::FlatCap )
3349 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3351 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3352 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3358 QTransform brushTransform;
3359 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3360 brushTransform.rotate( -segmentAngleDegrees );
3361 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3365 brushTransform.translate( -( lineThickness / 2 ), 0 );
3367 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3369 brush.setTransform( brushTransform );
3370 imagePainter.setBrush( brush );
3373 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3374 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3375 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3376 << prevSegmentPolygonEndRight.
toQPointF()
3377 << prevSegmentPolygonEndLeft.
toQPointF() );
3380 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3381 imagePainter.setBrush( Qt::NoBrush );
3382 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3383 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3384 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3385 << prevSegmentPolygonEndRight.
toQPointF()
3386 << prevSegmentPolygonEndLeft.
toQPointF() );
3387 imagePainter.setPen( Qt::NoPen );
3392 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3393 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3394 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3395 progressThroughImage = fmod( progressThroughImage, patternLength );
3398 segmentStartPoint = segmentEndPoint;
3399 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3400 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3408 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3409 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3426 auto res = std::make_unique<QgsRasterLineSymbolLayer>();
3428 if (
properties.contains( u
"line_width"_s ) )
3430 res->setWidth(
properties[u
"line_width"_s].toDouble() );
3432 if (
properties.contains( u
"line_width_unit"_s ) )
3436 if (
properties.contains( u
"width_map_unit_scale"_s ) )
3442 res->setPath(
properties[u
"imageFile"_s].toString() );
3446 res->setOffset(
properties[u
"offset"_s].toDouble() );
3448 if (
properties.contains( u
"offset_unit"_s ) )
3452 if (
properties.contains( u
"offset_map_unit_scale"_s ) )
3464 res->setOpacity(
properties[u
"alpha"_s].toDouble() );
3467 return res.release();
3474 map[u
"imageFile"_s] =
mPath;
3476 map[u
"line_width"_s] = QString::number(
mWidth );
3483 map[u
"offset"_s] = QString::number(
mOffset );
3487 map[u
"alpha"_s] = QString::number(
mOpacity );
3494 auto res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3506 return res.release();
3511 const QVariantMap::iterator it =
properties.find( u
"imageFile"_s );
3512 if ( it !=
properties.end() && it.value().userType() == QMetaType::Type::QString )
3528 return u
"RasterLine"_s;
3543 bool cached =
false;
3545 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3546 static_cast< int >( std::ceil( scaledHeight ) ) ),
3571 double strokeWidth =
mWidth;
3588 bool cached =
false;
3590 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3591 static_cast< int >( std::ceil( scaledHeight ) ) ),
3596 if ( useSelectedColor )
3601 const QBrush brush( sourceImage );
3671 auto res = std::make_unique<QgsLineburstSymbolLayer>();
3673 if (
properties.contains( u
"line_width"_s ) )
3675 res->setWidth(
properties[u
"line_width"_s].toDouble() );
3677 if (
properties.contains( u
"line_width_unit"_s ) )
3681 if (
properties.contains( u
"width_map_unit_scale"_s ) )
3688 res->setOffset(
properties[u
"offset"_s].toDouble() );
3690 if (
properties.contains( u
"offset_unit"_s ) )
3694 if (
properties.contains( u
"offset_map_unit_scale"_s ) )
3704 if (
properties.contains( u
"color_type"_s ) )
3711 if (
properties.contains( u
"gradient_color2"_s ) )
3726 return res.release();
3733 map[u
"line_width"_s] = QString::number(
mWidth );
3740 map[u
"offset"_s] = QString::number(
mOffset );
3757 auto res = std::make_unique< QgsLineburstSymbolLayer >();
3773 return res.release();
3778 return u
"Lineburst"_s;
3799 double strokeWidth =
mWidth;
3815 if ( useSelectedColor )
3819 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3830 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3842 gradient.setColorAt( 0.0, color1 );
3843 gradient.setColorAt( 1.0,
color2 );
3845 const QBrush brush( gradient );
3924 if ( props.contains( u
"line_width"_s ) )
3926 width = props[u
"line_width"_s].toDouble();
3928 else if ( props.contains( u
"outline_width"_s ) )
3930 width = props[u
"outline_width"_s].toDouble();
3932 else if ( props.contains( u
"width"_s ) )
3934 width = props[u
"width"_s].toDouble();
3939 if ( props.contains( u
"line_width_unit"_s ) )
3943 else if ( props.contains( u
"outline_width_unit"_s ) )
3947 else if ( props.contains( u
"width_unit"_s ) )
3952 if ( props.contains( u
"width_map_unit_scale"_s ) )
3954 if ( props.contains( u
"offset"_s ) )
3955 l->setOffset( props[u
"offset"_s].toDouble() );
3956 if ( props.contains( u
"offset_unit"_s ) )
3958 if ( props.contains( u
"offset_map_unit_scale"_s ) )
3960 if ( props.contains( u
"joinstyle"_s ) )
3962 if ( props.contains( u
"capstyle"_s ) )
3965 l->restoreOldDataDefinedProperties( props );
3972 return u
"FilledLine"_s;
4021 Qt::PenJoinStyle join = mPenJoinStyle;
4030 Qt::PenCapStyle cap = mPenCapStyle;
4046 const double prevOpacity = mFill->opacity();
4047 mFill->setOpacity( mFill->opacity() * context.
opacity() );
4054 if ( points.count() >= 2 )
4072 auto inputPoly = std::make_unique< QgsPolygon >(
static_cast< QgsLineString *
>( ls.release() ) );
4078 if ( !parts.empty() )
4106 std::unique_ptr< QgsAbstractGeometry > bufferedGeom =
QgsGeos::fromGeos( buffered.get() );
4108 for (
const QList< QPolygonF > &polygon : parts )
4110 QVector< QPolygonF > rings;
4111 for (
int i = 1; i < polygon.size(); ++i )
4112 rings << polygon.at( i );
4113 mFill->renderPolygon( polygon.value( 0 ), &rings, context.
feature(), context.
renderContext(), -1, useSelectedColor );
4121 mFill->setOpacity( prevOpacity );
4128 map[u
"line_width"_s] = QString::number(
mWidth );
4133 map[u
"offset"_s] = QString::number(
mOffset );
4148 res->setSubSymbol( mFill->clone() );
4149 return res.release();
4184 attr.unite( mFill->usedAttributes( context ) );
4192 if ( mFill && mFill->hasDataDefinedProperties() )
4201 mFill->setColor(
c );
4206 return mFill ? mFill->color() :
mColor;
4213 || ( mFill && mFill->usesMapUnits() );
4220 mFill->setMapUnitScale( scale );
4227 return mFill->mapUnitScale();
4236 mFill->setOutputUnit( unit );
4243 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,...
@ RenderLayerTree
The render is for a layer tree display where map based properties are not available and where avoidan...
@ 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.
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.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
QList< QPair< double, double > > BlankSegments
static QList< QList< BlankSegments > > parseBlankSegments(const QString &strBlankSegments, const QgsRenderContext &renderContext, Qgis::RenderUnit unit, QString &error)
Parse blank segments string representation strBlankSegments.
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.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
static const QString EXPR_GEOMETRY_POINT_COUNT
Inbuilt variable name for point count variable.
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
static const QString EXPR_GEOMETRY_RING_NUM
Inbuilt variable name for geometry ring number variable.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isCanceled() const
Tells whether the operation has been canceled already.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static std::unique_ptr< QgsFillSymbol > createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString layerType() const override
Returns a string that represents this layer type.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFilledLineSymbolLayer, using the settings serialized in the properties map (correspo...
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
~QgsFilledLineSymbolLayer() override
QgsFilledLineSymbolLayer(double width=DEFAULT_SIMPLELINE_WIDTH, QgsFillSymbol *fillSymbol=nullptr)
Constructor for QgsFilledLineSymbolLayer.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setColor(const QColor &c) override
Sets the "representative" color for the symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
QgsFilledLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
QgsMapUnitScale mapUnitScale() const override
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static bool segmentIntersection(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
A geometry is the spatial representation of a feature.
QVector< QgsGeometry > coerceToType(Qgis::WkbType type, double defaultZ=0, double defaultM=0, bool avoidDuplicates=true) const
Attempts to coerce this geometry into the specified destination type.
static geos::unique_ptr offsetCurve(const GEOSGeometry *geometry, double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg=nullptr)
Directly calculates the offset curve for a GEOS geometry object and returns a GEOS geometry result.
QgsAbstractGeometry * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlags())
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
void addStopsToGradient(QGradient *gradient, double opacity=1) const
Copy color ramp stops to a QGradient.
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.
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
QgsLineSymbolLayer(const QgsLineSymbolLayer &other)=delete
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.
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.
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.
Q_DECL_DEPRECATED bool rotateMarker() const
Shall the marker be rotated.
std::unique_ptr< QgsMarkerSymbol > mMarker
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsMarkerLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
double width() const override
Returns the estimated width for the line symbol layer.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsMarkerLineSymbolLayer, using the settings serialized in the properties map (correspo...
QgsMarkerLineSymbolLayer(bool rotateMarker=DEFAULT_MARKERLINE_ROTATE, double interval=DEFAULT_MARKERLINE_INTERVAL)
Constructor for QgsMarkerLineSymbolLayer.
void setWidth(double width) override
Sets the width of the line symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
Q_DECL_DEPRECATED void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
~QgsMarkerLineSymbolLayer() override
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QString layerType() const override
Returns a string that represents this layer type.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsMarkerLineSymbolLayer from an SLD XML DOM element.
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
Abstract base class for marker symbol layers.
A marker symbol type, for rendering Point and MultiPoint geometries.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Resolves relative paths into absolute paths and vice versa.
QgsPointXY project(double distance, double bearing) const
Returns a new point which corresponds to this point projected by a specified distance in a specified ...
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 ...
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
A store for object properties.
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.
~QgsRasterLineSymbolLayer() override
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.
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.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void setDrawInsidePolygon(bool drawInsidePolygon)
Sets whether the line should only be drawn inside polygons, and any portion of the line which falls o...
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QgsMapUnitScale mapUnitScale() const override
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QVector< qreal > customDashVector() const
Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the outline of polygon, using the given render context.
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
void setCustomDashPatternMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for lengths used in the custom dash pattern.
void setTrimDistanceEndMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the end of the line.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void setTrimDistanceEnd(double distance)
Sets the trim distance for the end of the line, which dictates a length from the end of the line at w...
double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets offset.
QgsSimpleLineSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, double width=DEFAULT_SIMPLELINE_WIDTH, Qt::PenStyle penStyle=DEFAULT_SIMPLELINE_PENSTYLE)
Constructor for QgsSimpleLineSymbolLayer.
~QgsSimpleLineSymbolLayer() override
void setUseCustomDashPattern(bool b)
Sets whether the line uses a custom dash pattern.
void setTweakDashPatternOnCorners(bool enabled)
Sets whether dash patterns tweaks should be applied on sharp corners, to ensure that a double-length ...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
void setCustomDashVector(const QVector< qreal > &vector)
Sets the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ren...
void setDashPatternOffset(double offset)
Sets the dash pattern offset, which dictates how far along the dash pattern the pattern should start ...
QColor dxfColor(QgsSymbolRenderContext &context) const override
Gets color.
QString layerType() const override
Returns a string that represents this layer type.
void setDashPatternOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the dash pattern offset.
QgsSimpleLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
void setAlignDashPattern(bool enabled)
Sets whether dash patterns should be aligned to the start and end of lines, by applying subtle tweaks...
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleLineSymbolLayer from an SLD XML DOM element.
double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets line width.
void setTrimDistanceStartMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the start of the line.
QVector< qreal > dxfCustomDashPattern(Qgis::RenderUnit &unit) const override
Gets dash pattern.
Qt::PenCapStyle penCapStyle() const
Returns the pen cap style used to render the line (e.g.
void setTrimDistanceEndUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the end of the line.
void setDashPatternOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the dash pattern offset.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
Q_DECL_DEPRECATED void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setTrimDistanceStart(double distance)
Sets the trim distance for the start of the line, which dictates a length from the start of the line ...
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setTrimDistanceStartUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the start of the line.
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
void setCustomDashPatternUnit(Qgis::RenderUnit unit)
Sets the unit for lengths used in the custom dash pattern.
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void setExtraProperties(const QVariantMap &properties)
Sets the open ended set of properties that can drive/inform the SLD encoding.
QVariantMap extraProperties() const
Returns the open ended set of properties that can drive/inform the SLD encoding.
static QString encodePenStyle(Qt::PenStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static Q_DECL_DEPRECATED bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static std::unique_ptr< QgsSymbolLayer > createMarkerLayerFromSld(QDomElement &element)
Creates a new marker layer from a SLD DOM element.
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static QString encodeColor(const QColor &color)
static Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static Q_DECL_DEPRECATED void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
Creates an SLD geometry element.
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static Qt::PenStyle decodePenStyle(const QString &str)
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, QgsSldExportContext &context, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QString encodeRealVector(const QVector< qreal > &v)
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.
@ BlankSegments
String list of distance to define blank segments along line for templated line symbol layers.
@ 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.
QgsSymbolLayer(const QgsSymbolLayer &other)
Encapsulates the context in which a symbol is being rendered.
const QgsFeature * feature() const
Returns the current feature being rendered.
Qgis::GeometryType originalGeometryType() const
Returns the geometry type for the original feature geometry being rendered.
QgsFields fields() const
Fields of the layer.
int geometryPartNum() const
Part number of current geometry.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
qreal opacity() const
Returns the opacity for the symbol.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for all rendered symbols.
qreal opacity() const
Returns the opacity for the symbol.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
Qgis::SymbolType type() const
Returns the symbol's type.
bool rotateSymbols() const
Returns true if the repeating symbols be rotated to match their line segment orientation.
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...
void setMapUnitScale(const QgsMapUnitScale &scale) final
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.
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
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 destLayer.
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.
Qgis::RenderUnit offsetAlongLineUnit() const
Returns the unit used for calculating the offset along line for symbols.
Qgis::RenderUnit outputUnit() const final
Returns the units to use for sizes and widths within the symbol layer.
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.
QgsMapUnitScale mapUnitScale() const final
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.
Qgis::RenderUnit blankSegmentsUnit() const
Returns the unit for for blank segments start and end distances.
void setBlankSegmentsUnit(Qgis::RenderUnit unit)
Sets the unit for blank segments start and end distances.
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).
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QMap< QString, QString > QgsStringMap
#define DEFAULT_MARKERLINE_INTERVAL
#define DEFAULT_SIMPLELINE_WIDTH
#define DEFAULT_MARKERLINE_ROTATE
#define DEFAULT_SIMPLELINE_PENSTYLE
#define DEFAULT_SIMPLELINE_COLOR
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
Single variable definition for use within a QgsExpressionContextScope.
Qgis::VertexType type
Vertex type.