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;
592 toSld( doc, element, context );
597 if ( mPenStyle == Qt::NoPen )
601 QDomElement symbolizerElem = doc.createElement( u
"se:LineSymbolizer"_s );
602 if ( !props.value( u
"uom"_s, QString() ).toString().isEmpty() )
603 symbolizerElem.setAttribute( u
"uom"_s, props.value( u
"uom"_s, QString() ).toString() );
604 element.appendChild( symbolizerElem );
610 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
611 symbolizerElem.appendChild( strokeElem );
613 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
622 QDomElement perpOffsetElem = doc.createElement( u
"se:PerpendicularOffset"_s );
625 symbolizerElem.appendChild( perpOffsetElem );
632 if ( mUseCustomDashPattern )
635 mPen.color(), mPenJoinStyle,
636 mPenCapStyle,
mOffset, &mCustomDashVector );
649 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
650 if ( strokeElem.isNull() )
667 QDomElement perpOffsetElem = element.firstChildElement( u
"PerpendicularOffset"_s );
668 if ( !perpOffsetElem.isNull() )
671 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
676 double scaleFactor = 1.0;
677 const QString uom = element.attribute( u
"uom"_s );
692void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
698 bool hasStrokeWidthExpression =
false;
705 pen.setWidthF( scaledWidth );
706 selPen.setWidthF( scaledWidth );
707 hasStrokeWidthExpression =
true;
716 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
717 pen.setColor( penColor );
731 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
736 const QStringList dashList = customDashString.split(
';' );
737 QVector<qreal> dashVector;
738 for (
const QString &dash : dashList )
742 pen.setDashPattern( dashVector );
748 QVector<qreal> scaledVector;
749 for (
double v : std::as_const( mCustomDashVector ) )
754 mPen.setDashPattern( scaledVector );
758 double patternOffset = mDashPatternOffset;
791void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
793 if ( pen.dashPattern().empty() || points.size() < 2 )
796 if ( pen.widthF() <= 1.0 )
798 pen.setWidthF( 1.0001 );
801 QVector< qreal > sourcePattern = pen.dashPattern();
802 const double dashWidthDiv = pen.widthF();
804 for (
int i = 0; i < sourcePattern.size(); ++ i )
805 sourcePattern[i] *= pen.widthF();
807 QVector< qreal > buffer;
808 QPolygonF bufferedPoints;
809 QPolygonF previousSegmentBuffer;
814 auto ptIt = points.constBegin();
815 double totalBufferLength = 0;
816 int patternIndex = 0;
817 double currentRemainingDashLength = 0;
818 double currentRemainingGapLength = 0;
820 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
822 QVector< qreal > result;
823 result.reserve( buffer.size() );
824 for (
auto it = buffer.begin(); it != buffer.end(); )
828 while ( dash == 0 && !result.empty() )
830 result.last() += gap;
832 if ( it == buffer.end() )
837 while ( gap == 0 && it != buffer.end() )
842 result << dash << gap;
847 double currentBufferLineLength = 0;
848 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
849 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
851 if ( buffer.empty() || bufferedPoints.size() < 2 )
856 if ( currentRemainingDashLength )
859 buffer << currentRemainingDashLength << 0.0;
860 totalBufferLength += currentRemainingDashLength;
862 QVector< qreal > compressed = compressPattern( buffer );
863 if ( !currentRemainingDashLength )
866 totalBufferLength -= compressed.last();
867 compressed.last() = 0;
871 const double scaleFactor = currentBufferLineLength / totalBufferLength;
873 bool shouldFlushPreviousSegmentBuffer =
false;
875 if ( !previousSegmentBuffer.empty() )
879 if ( !firstDashSubstring.empty() )
885 compressed = compressed.mid( 2 );
886 shouldFlushPreviousSegmentBuffer = !compressed.empty();
889 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
891 QPen adjustedPen = pen;
892 adjustedPen.setStyle( Qt::SolidLine );
893 painter->setPen( adjustedPen );
895 path.addPolygon( previousSegmentBuffer );
896 painter->drawPath( path );
897 previousSegmentBuffer.clear();
900 double finalDash = 0;
907 if ( !compressed.empty() )
909 finalDash = compressed.at( compressed.size() - 2 );
910 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
912 const QPolygonF thisPoints = bufferedPoints;
918 previousSegmentBuffer << bufferedPoints;
922 currentBufferLineLength = 0;
923 currentRemainingDashLength = 0;
924 currentRemainingGapLength = 0;
925 totalBufferLength = 0;
928 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
930 QPen adjustedPen = pen;
931 if ( !compressed.empty() )
934 compressed = compressed.mid( 0, 32 );
935 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
936 adjustedPen.setDashPattern( compressed );
940 adjustedPen.setStyle( Qt::SolidLine );
943 painter->setPen( adjustedPen );
945 path.addPolygon( bufferedPoints );
946 painter->drawPath( path );
949 bufferedPoints.clear();
955 bufferedPoints << p2;
956 for ( ; ptIt != points.constEnd(); ++ptIt )
964 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
965 currentBufferLineLength += remainingSegmentDistance;
969 if ( currentRemainingDashLength > 0 )
972 if ( remainingSegmentDistance >= currentRemainingDashLength )
975 buffer << currentRemainingDashLength << 0.0;
976 totalBufferLength += currentRemainingDashLength;
977 remainingSegmentDistance -= currentRemainingDashLength;
979 currentRemainingDashLength = 0.0;
980 currentRemainingGapLength = sourcePattern.at( patternIndex );
981 if ( currentRemainingGapLength == 0.0 )
989 buffer << remainingSegmentDistance << 0.0;
990 totalBufferLength += remainingSegmentDistance;
991 currentRemainingDashLength -= remainingSegmentDistance;
995 if ( currentRemainingGapLength > 0 )
998 if ( remainingSegmentDistance >= currentRemainingGapLength )
1001 buffer << 0.0 << currentRemainingGapLength;
1002 totalBufferLength += currentRemainingGapLength;
1003 remainingSegmentDistance -= currentRemainingGapLength;
1004 currentRemainingGapLength = 0.0;
1010 buffer << 0.0 << remainingSegmentDistance;
1011 totalBufferLength += remainingSegmentDistance;
1012 currentRemainingGapLength -= remainingSegmentDistance;
1017 if ( patternIndex + 1 >= sourcePattern.size() )
1022 const double nextPatternDashLength = sourcePattern.at( patternIndex );
1023 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
1024 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1026 buffer << nextPatternDashLength << nextPatternGapLength;
1027 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1028 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1031 else if ( nextPatternDashLength <= remainingSegmentDistance )
1034 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1035 totalBufferLength += remainingSegmentDistance;
1036 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1037 currentRemainingDashLength = 0;
1044 buffer << remainingSegmentDistance << 0.0;
1045 totalBufferLength += remainingSegmentDistance;
1046 currentRemainingGapLength = 0;
1047 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1052 bufferedPoints << p1;
1053 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1055 QPointF nextPoint = *( ptIt + 1 );
1061 flushBuffer( &nextPoint );
1062 bufferedPoints << p1;
1065 if ( patternIndex % 2 == 1 )
1069 currentRemainingDashLength = sourcePattern.at( patternIndex );
1076 flushBuffer(
nullptr );
1077 if ( !previousSegmentBuffer.empty() )
1079 QPen adjustedPen = pen;
1080 adjustedPen.setStyle( Qt::SolidLine );
1081 painter->setPen( adjustedPen );
1083 path.addPolygon( previousSegmentBuffer );
1084 painter->drawPath( path );
1085 previousSegmentBuffer.clear();
1091 if ( mDrawInsidePolygon )
1105 unit = mCustomDashPatternUnit;
1106 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1143 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1148 return mAlignDashPattern;
1158 return mPatternCartographicTweakOnSharpCorners;
1163 mPatternCartographicTweakOnSharpCorners =
enabled;
1188 : mRotateSymbols( rotateSymbol )
1228 if ( mRenderingFeature )
1232 mFeatureSymbolOpacity = context.
opacity();
1233 mCurrentFeatureIsSelected = useSelectedColor;
1251 QString placementString = exprVal.toString();
1252 if ( placementString.compare(
"interval"_L1, Qt::CaseInsensitive ) == 0 )
1256 else if ( placementString.compare(
"vertex"_L1, Qt::CaseInsensitive ) == 0 )
1260 else if ( placementString.compare(
"innervertices"_L1, Qt::CaseInsensitive ) == 0 )
1264 else if ( placementString.compare(
"lastvertex"_L1, Qt::CaseInsensitive ) == 0 )
1268 else if ( placementString.compare(
"firstvertex"_L1, Qt::CaseInsensitive ) == 0 )
1272 else if ( placementString.compare(
"centerpoint"_L1, Qt::CaseInsensitive ) == 0 )
1276 else if ( placementString.compare(
"curvepoint"_L1, Qt::CaseInsensitive ) == 0 )
1280 else if ( placementString.compare(
"segmentcenter"_L1, Qt::CaseInsensitive ) == 0 )
1293 double averageOver = mAverageAngleLength;
1308 if ( !error.isEmpty() )
1310 QgsDebugError( u
"Badly formatted blank segment '%1', skip it: %2"_s.arg( strBlankSegments ).arg( error ) );
1316 if ( iPart >= 0 &&
mRingIndex >= 0 && iPart < allBlankSegments.count() &&
mRingIndex < allBlankSegments.at( iPart ).count() )
1318 blankSegments = allBlankSegments.at( iPart ).at(
mRingIndex );
1326 renderPolylineInterval( points, context, averageOver, blankSegments );
1328 renderPolylineCentral( points, context, averageOver, blankSegments );
1332 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1335 mHasRenderedFirstPart = mRenderingFeature;
1351 for (
int part = 0; part < mline.count(); ++part )
1353 const QPolygonF &points2 = mline[ part ];
1356 renderPolylineInterval( points2, context, averageOver, blankSegments );
1358 renderPolylineCentral( points2, context, averageOver, blankSegments );
1366 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1369 mHasRenderedFirstPart = mRenderingFeature;
1389 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1419 for (
int i = 0; i < rings->size(); ++i )
1454 mIntervalUnit = unit;
1455 mOffsetAlongLineUnit = unit;
1456 mAverageAngleLengthUnit = unit;
1482 map[u
"interval"_s] = QString::number(
interval() );
1483 map[u
"offset"_s] = QString::number(
mOffset );
1491 map[u
"average_angle_length"_s] = QString::number( mAverageAngleLength );
1498 map[u
"ring_filter"_s] = QString::number(
static_cast< int >(
mRingFilter ) );
1499 map[u
"place_on_every_part"_s] = mPlaceOnEveryPart;
1505 return mPlaceOnEveryPart
1515 mRenderingFeature =
true;
1516 mHasRenderedFirstPart =
false;
1521 mRenderingFeature =
false;
1532 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1533 mFeatureSymbolOpacity = 1;
1567 if (
properties.contains( u
"offset_unit"_s ) )
1571 if (
properties.contains( u
"interval_unit"_s ) )
1575 if (
properties.contains( u
"offset_along_line"_s ) )
1579 if (
properties.contains( u
"offset_along_line_unit"_s ) )
1583 if (
properties.contains( ( u
"offset_along_line_map_unit_scale"_s ) ) )
1588 if (
properties.contains( u
"offset_map_unit_scale"_s ) )
1592 if (
properties.contains( u
"interval_map_unit_scale"_s ) )
1597 if (
properties.contains( u
"average_angle_length"_s ) )
1601 if (
properties.contains( u
"average_angle_unit"_s ) )
1605 if (
properties.contains( ( u
"average_angle_map_unit_scale"_s ) ) )
1609 if (
properties.contains( u
"blank_segments_unit"_s ) )
1616 if (
properties[u
"placement"_s] ==
"vertex"_L1 )
1618 else if (
properties[u
"placement"_s] ==
"lastvertex"_L1 )
1620 else if (
properties[u
"placement"_s] ==
"firstvertex"_L1 )
1622 else if (
properties[u
"placement"_s] ==
"centralpoint"_L1 )
1624 else if (
properties[u
"placement"_s] ==
"curvepoint"_L1 )
1626 else if (
properties[u
"placement"_s] ==
"segmentcenter"_L1 )
1631 else if (
properties.contains( u
"placements"_s ) )
1637 if (
properties.contains( u
"ring_filter"_s ) )
1653class BlankSegmentsWalker
1658 : mBlankSegments( blankSegments )
1660 , mItBlankSegment( blankSegments.cbegin() )
1662 mDistances.reserve( mPoints.count() );
1666 bool insideBlankSegment(
double distance )
1668 while ( mItBlankSegment != mBlankSegments.cend() && distance > mItBlankSegment->second )
1673 return ( mItBlankSegment != mBlankSegments.cend() && distance >= mItBlankSegment->first );
1678 bool insideBlankSegment(
const QPointF &point,
int pointIndex )
1680 if ( pointIndex < 0 || pointIndex >= mPoints.count() )
1684 if ( pointIndex >= mDistances.count() )
1686 for (
int i =
static_cast<int>( mDistances.count() ); i < pointIndex + 1; i++ )
1688 const QPointF diff = mPoints.at( i ) - mPoints.at( i - 1 );
1689 const double distance = std::sqrt( std::pow( diff.x(), 2 ) + std::pow( diff.y(), 2 ) );
1690 const double totalDistance = distance + mDistances.last();
1691 mDistances << totalDistance;
1695 const QPointF diff = mPoints.at( pointIndex ) - point;
1696 const double distance = std::sqrt( std::pow( diff.x(), 2 ) + std::pow( diff.y(), 2 ) );
1697 const double currentDistance = mDistances.at( pointIndex ) + distance;
1699 return insideBlankSegment( currentDistance );
1705 const QPolygonF &mPoints;
1706 QList<double> mDistances;
1707 QgsBlankSegmentUtils::BlankSegments::const_iterator mItBlankSegment;
1716 if ( points.isEmpty() )
1720 double lengthLeft = 0;
1725 QgsExpressionContextScope *scope =
new QgsExpressionContextScope();
1752 constexpr double EPSILON = 1e-5;
1753 if ( painterUnitInterval <
EPSILON )
1756 double painterUnitOffsetAlongLine = 0;
1759 double totalLength = -1;
1780 if ( points.isClosed() )
1782 if ( painterUnitOffsetAlongLine > 0 )
1784 if ( totalLength < 0 )
1786 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1788 else if ( painterUnitOffsetAlongLine < 0 )
1790 if ( totalLength < 0 )
1792 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1804 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1806 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1808 QVector< QPointF > angleStartPoints;
1809 QVector< QPointF > symbolPoints;
1810 QVector< QPointF > angleEndPoints;
1819 QList<int> pointIndices;
1820 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft, blankSegments.isEmpty() ?
nullptr : &pointIndices );
1822 if ( symbolPoints.empty() )
1828 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1831 symbolPoints.pop_back();
1834 angleEndPoints.reserve( symbolPoints.size() );
1835 angleStartPoints.reserve( symbolPoints.size() );
1836 if ( averageOver <= painterUnitOffsetAlongLine )
1838 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver,
nullptr, 0, symbolPoints.size() );
1842 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0,
nullptr, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1844 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver,
nullptr, 0, symbolPoints.size() );
1847 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
1848 for (
int i = 0; i < symbolPoints.size(); ++ i )
1853 const QPointF pt = symbolPoints[i];
1854 if ( i < pointIndices.count() && blankSegmentsWalker.insideBlankSegment( pt, pointIndices.at( i ) ) )
1858 const QPointF startPt = angleStartPoints[i];
1859 const QPointF endPt = angleEndPoints[i];
1861 Line l( startPt, endPt );
1877 QPointF lastPt = points[0];
1878 BlankSegmentsWalker itBlankSegment( points, blankSegments );
1879 for (
int i = 1; i < points.count(); ++i )
1884 const QPointF &pt = points[i];
1890 Line l( lastPt, pt );
1891 QPointF diff = l.diffForInterval( painterUnitInterval );
1896 double c = 1 - lengthLeft / painterUnitInterval;
1898 lengthLeft += l.length();
1907 while ( lengthLeft > painterUnitInterval )
1914 if ( !itBlankSegment.insideBlankSegment( lastPt, i - 1 ) )
1920 lengthLeft -= painterUnitInterval;
1929static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1932 double a1 = Line( prevPt, pt ).angle();
1933 double a2 = Line( pt, nextPt ).angle();
1934 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1936 return std::atan2( unitY, unitX );
1941 if ( points.isEmpty() )
1946 int i = -1, maxCount = 0;
1947 bool isRing =
false;
1949 QgsExpressionContextScope *scope =
new QgsExpressionContextScope();
1961 double totalLength = -1;
1981 if ( points.isClosed() )
1985 if ( totalLength < 0 )
1991 if ( totalLength < 0 )
2065 i = points.count() - 1;
2067 maxCount = points.count();
2075 maxCount = points.count() - 1;
2083 maxCount = points.count();
2084 if ( points.first() == points.last() )
2101 renderOffsetVertexAlongLine( points, i, distance, context,
placement, blankSegments );
2108 prevPoint = points.at( 0 );
2110 QPointF symbolPoint;
2111 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
2112 for ( ; i < maxCount; ++i )
2123 QPointF currentPoint = points.at( i );
2124 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2125 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2128 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2129 currentPoint.x() - prevPoint.x() );
2132 prevPoint = currentPoint;
2136 symbolPoint = points.at( i );
2140 double angle = markerAngle( points, isRing, i );
2145 mFinalVertex = symbolPoint;
2147 && !blankSegmentsWalker.insideBlankSegment( symbolPoint, i ) )
2152double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2155 const QPointF &pt = points[vertex];
2157 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2159 int prevIndex = vertex - 1;
2160 int nextIndex = vertex + 1;
2162 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2164 prevIndex = points.count() - 2;
2168 QPointF prevPoint, nextPoint;
2169 while ( prevIndex >= 0 )
2171 prevPoint = points[ prevIndex ];
2172 if ( prevPoint != pt )
2179 while ( nextIndex < points.count() )
2181 nextPoint = points[ nextIndex ];
2182 if ( nextPoint != pt )
2189 if ( prevIndex >= 0 && nextIndex < points.count() )
2191 angle = _averageAngle( prevPoint, pt, nextPoint );
2198 while ( vertex < points.size() - 1 )
2200 const QPointF &nextPt = points[vertex + 1];
2203 angle = Line( pt, nextPt ).angle();
2212 while ( vertex >= 1 )
2214 const QPointF &prevPt = points[vertex - 1];
2217 angle = Line( prevPt, pt ).angle();
2229 if ( points.isEmpty() )
2239 bool isRing =
false;
2240 if ( points.first() == points.last() )
2242 double angle = markerAngle( points, isRing, vertex );
2245 mFinalVertex = points[vertex];
2251 int pointIncrement = distance > 0 ? 1 : -1;
2252 QPointF previousPoint = points[vertex];
2253 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2254 int endPoint = distance > 0 ? points.count() - 1 : 0;
2255 double distanceLeft = std::fabs( distance );
2256 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
2258 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2260 const QPointF &pt = points[i];
2262 if ( previousPoint == pt )
2266 Line l( previousPoint, pt );
2268 if ( distanceLeft < l.length() )
2271 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2277 mFinalVertex = markerPoint;
2279 && !blankSegmentsWalker.insideBlankSegment( markerPoint, i - 1 ) )
2284 distanceLeft -= l.length();
2291void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
2292 QList<int> *pointIndices,
2293 double initialLag,
int numberPointsRequired )
2298 QVector< QPointF > points = p;
2299 const bool closedRing = points.first() == points.last();
2301 double lengthLeft = initialOffset;
2303 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2304 if ( initialLagLeft < 0 && closedRing )
2307 QPointF lastPt = points.constLast();
2308 QVector< QPointF > pseudoPoints;
2309 for (
int i = points.count() - 2; i > 0; --i )
2311 if ( initialLagLeft >= 0 )
2316 const QPointF &pt = points[i];
2321 Line l( lastPt, pt );
2322 initialLagLeft += l.length();
2327 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2329 points = pseudoPoints;
2334 while ( initialLagLeft < 0 )
2336 dest << points.constFirst();
2337 initialLagLeft += intervalPainterUnits;
2340 if ( initialLag > 0 )
2342 lengthLeft += intervalPainterUnits - initialLagLeft;
2345 QPointF lastPt = points[0];
2346 for (
int i = 1; i < points.count(); ++i )
2348 const QPointF &pt = points[i];
2352 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2361 Line l( lastPt, pt );
2362 QPointF diff = l.diffForInterval( intervalPainterUnits );
2366 double c = 1 - lengthLeft / intervalPainterUnits;
2368 lengthLeft += l.length();
2371 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2375 lengthLeft -= intervalPainterUnits;
2378 *pointIndices << i - 1;
2381 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2386 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2390 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2397 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2400 while ( dest.size() < numberPointsRequired )
2401 dest << points.constLast();
2407 if ( !points.isEmpty() )
2411 QPolygonF::const_iterator it = points.constBegin();
2413 for ( ++it; it != points.constEnd(); ++it )
2415 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2416 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2422 const double midPoint = length / 2;
2424 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
2425 if ( blankSegmentsWalker.insideBlankSegment( midPoint ) )
2429 double thisSymbolAngle = 0;
2431 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2433 QVector< QPointF > angleStartPoints;
2434 QVector< QPointF > symbolPoints;
2435 QVector< QPointF > angleEndPoints;
2439 collectOffsetPoints( points, symbolPoints, midPoint, midPoint,
nullptr, 0.0, 2 );
2440 collectOffsetPoints( points, angleStartPoints, midPoint, 0,
nullptr, averageAngleOver, 2 );
2441 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver,
nullptr, 0, 2 );
2443 pt = symbolPoints.at( 1 );
2444 Line l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2445 thisSymbolAngle = l.angle();
2450 it = points.constBegin();
2452 qreal last_at = 0, next_at = 0;
2454 for ( ++it; it != points.constEnd(); ++it )
2457 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2458 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2459 if ( next_at >= midPoint )
2466 Line l( last, next );
2467 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2468 pt = last + ( next - last ) * k;
2469 thisSymbolAngle = l.angle();
2521 if ( props.contains( u
"interval"_s ) )
2522 interval = props[u
"interval"_s].toDouble();
2523 if ( props.contains( u
"rotate"_s ) )
2524 rotate = ( props[u
"rotate"_s].toString() ==
"1"_L1 );
2526 auto x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2533 return u
"MarkerLine"_s;
2553 mMarker->setRenderHints( hints );
2575 toSld( doc, element, context );
2581 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2583 QDomElement symbolizerElem = doc.createElement( u
"se:LineSymbolizer"_s );
2584 if ( !props.value( u
"uom"_s, QString() ).toString().isEmpty() )
2585 symbolizerElem.setAttribute( u
"uom"_s, props.value( u
"uom"_s, QString() ).toString() );
2586 element.appendChild( symbolizerElem );
2616 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
2617 symbolizerElem.appendChild( strokeElem );
2620 QDomElement graphicStrokeElem = doc.createElement( u
"se:GraphicStroke"_s );
2621 strokeElem.appendChild( graphicStrokeElem );
2626 markerLayer->writeSldMarker( doc, graphicStrokeElem, context );
2634 QgsDebugError( u
"Missing marker line symbol layer. Skip it."_s );
2637 if ( !gap.isEmpty() )
2639 QDomElement gapElem = doc.createElement( u
"se:Gap"_s );
2641 graphicStrokeElem.appendChild( gapElem );
2646 QDomElement perpOffsetElem = doc.createElement( u
"se:PerpendicularOffset"_s );
2649 symbolizerElem.appendChild( perpOffsetElem );
2659 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
2660 if ( strokeElem.isNull() )
2663 QDomElement graphicStrokeElem = strokeElem.firstChildElement( u
"GraphicStroke"_s );
2664 if ( graphicStrokeElem.isNull() )
2672 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2674 if ( it.key() ==
"placement"_L1 )
2676 if ( it.value() ==
"points"_L1 )
2678 else if ( it.value() ==
"firstPoint"_L1 )
2680 else if ( it.value() ==
"lastPoint"_L1 )
2682 else if ( it.value() ==
"centralPoint"_L1 )
2685 else if ( it.value() ==
"rotateMarker"_L1 )
2691 std::unique_ptr< QgsMarkerSymbol > marker;
2697 layers.append( l.release() );
2698 marker = std::make_unique<QgsMarkerSymbol>( layers );
2705 QDomElement gapElem = graphicStrokeElem.firstChildElement( u
"Gap"_s );
2706 if ( !gapElem.isNull() )
2709 double d = gapElem.firstChild().firstChild().nodeValue().toDouble( &ok );
2715 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( u
"PerpendicularOffset"_s );
2716 if ( !perpOffsetElem.isNull() )
2719 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2724 double scaleFactor = 1.0;
2725 const QString uom = element.attribute( u
"uom"_s );
2748 mMarker->setDataDefinedSize( property );
2755 const double prevOpacity =
mMarker->opacity();
2758 mMarker->setOpacity( prevOpacity );
2763 mMarker->setLineAngle( angle );
2781 mMarker->renderPoint( point, feature, context, layer, selected );
2793 return mMarker->size( context );
2799 mMarker->setOutputUnit( unit );
2817 attr.unite(
mMarker->usedAttributes( context ) );
2832 return (
mMarker->size( context ) / 2.0 ) +
2854 if ( props.contains( u
"interval"_s ) )
2855 interval = props[u
"interval"_s].toDouble();
2856 if ( props.contains( u
"rotate"_s ) )
2857 rotate = ( props[u
"rotate"_s] ==
"1"_L1 );
2859 auto x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2861 if ( props.contains( u
"hash_angle"_s ) )
2863 x->setHashAngle( props[u
"hash_angle"_s].toDouble() );
2866 if ( props.contains( u
"hash_length"_s ) )
2867 x->setHashLength( props[u
"hash_length"_s].toDouble() );
2869 if ( props.contains( u
"hash_length_unit"_s ) )
2872 if ( props.contains( u
"hash_length_map_unit_scale"_s ) )
2880 return u
"HashLine"_s;
2889 mHashSymbol->setRenderHints( hints );
2902 map[ u
"hash_angle"_s ] = QString::number( mHashAngle );
2904 map[u
"hash_length"_s] = QString::number( mHashLength );
2915 x->setHashAngle( mHashAngle );
2916 x->setHashLength( mHashLength );
2917 x->setHashLengthUnit( mHashLengthUnit );
2918 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2924 mHashSymbol->setColor(
color );
2930 return mHashSymbol ? mHashSymbol->color() :
mColor;
2935 return mHashSymbol.get();
2946 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2947 mColor = mHashSymbol->color();
2953 mHashLength =
width;
2968 return ( mHashSymbol->width( context ) / 2.0 )
2976 mHashSymbol->setOutputUnit( unit );
2983 attr.unite( mHashSymbol->usedAttributes( context ) );
2991 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
3000 mHashSymbol->setDataDefinedWidth( property );
3014 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
3019 mSymbolLineAngle = angle;
3024 return mSymbolAngle;
3029 mSymbolAngle = angle;
3034 double lineLength = mHashLength;
3040 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
3054 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
3059 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
3076 const double prevOpacity = mHashSymbol->opacity();
3077 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
3079 mHashSymbol->setOpacity( prevOpacity );
3098 QPolygonF offsetPoints;
3101 renderLine( points, context, patternThickness, patternLength, brush );
3110 renderLine( part, context, patternThickness, patternLength, brush );
3115void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3116 const double patternLength,
const QBrush &sourceBrush )
3122 QBrush brush = sourceBrush;
3127 QPolygonF inputPoints;
3128 inputPoints.reserve( points.size() );
3130 double minX = std::numeric_limits< double >::max();
3131 double minY = std::numeric_limits< double >::max();
3132 double maxX = std::numeric_limits< double >::lowest();
3133 double maxY = std::numeric_limits< double >::lowest();
3135 for (
const QPointF &pt : std::as_const( points ) )
3142 minX = std::min( minX, pt.x() );
3143 minY = std::min( minY, pt.y() );
3144 maxX = std::max( maxX, pt.x() );
3145 maxY = std::max( maxY, pt.y() );
3148 if ( inputPoints.size() < 2 )
3152 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3154 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3157 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3158 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3160 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3161 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3163 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3164 if ( temporaryImage.isNull() )
3173 temporaryImage.fill( Qt::transparent );
3196 QPainterPathStroker stroker;
3197 stroker.setWidth( lineThickness );
3198 stroker.setCapStyle( cap );
3199 stroker.setJoinStyle( join );
3202 path.addPolygon( inputPoints );
3203 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3206 QPainter imagePainter;
3207 imagePainter.begin( &temporaryImage );
3209 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3211 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3212 imagePainter.setPen( Qt::NoPen );
3214 QPointF segmentStartPoint = inputPoints.at( 0 );
3217 double progressThroughImage = 0;
3219 QgsPoint prevSegmentPolygonEndLeft;
3220 QgsPoint prevSegmentPolygonEndRight;
3223 QgsPoint startLinePolygonLeft;
3224 QgsPoint startLinePolygonRight;
3226 for (
int i = 1; i < inputPoints.size(); ++i )
3231 const QPointF segmentEndPoint = inputPoints.at( i );
3233 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3236 QgsPoint thisSegmentPolygonEndLeft;
3237 QgsPoint thisSegmentPolygonEndRight;
3239 QgsPoint thisSegmentPolygonEndLeftForPainter;
3240 QgsPoint thisSegmentPolygonEndRightForPainter;
3248 const QgsPoint startPointLeft = QgsPoint( segmentStartPoint ).project( lineThickness / 2, segmentAngleDegrees );
3249 const QgsPoint endPointLeft = QgsPoint( segmentEndPoint ).project( lineThickness / 2, segmentAngleDegrees );
3250 const QgsPoint startPointRight = QgsPoint( segmentStartPoint ).project( -lineThickness / 2, segmentAngleDegrees );
3251 const QgsPoint endPointRight = QgsPoint( segmentEndPoint ).project( -lineThickness / 2, segmentAngleDegrees );
3255 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtilsBase::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3256 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3259 const QgsPoint lastSegmentStartPointLeft = QgsPoint( points.at( points.size() - 2 ) ).project( lineThickness / 2, lastSegmentAngleDegrees );
3260 const QgsPoint lastSegmentEndPointLeft = QgsPoint( segmentStartPoint ).project( lineThickness / 2, lastSegmentAngleDegrees );
3261 const QgsPoint lastSegmentStartPointRight = QgsPoint( points.at( points.size() - 2 ) ).project( -lineThickness / 2, lastSegmentAngleDegrees );
3262 const QgsPoint lastSegmentEndPointRight = QgsPoint( segmentStartPoint ).project( -lineThickness / 2, lastSegmentAngleDegrees );
3267 QgsPoint intersectionPoint;
3268 bool isIntersection =
false;
3270 if ( !isIntersection )
3271 prevSegmentPolygonEndLeft = startPointLeft;
3272 isIntersection =
false;
3273 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3274 if ( !isIntersection )
3275 prevSegmentPolygonEndRight = startPointRight;
3277 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3278 startLinePolygonRight = prevSegmentPolygonEndRight;
3282 prevSegmentPolygonEndLeft = QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3283 if ( cap != Qt::PenCapStyle::FlatCap )
3284 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3285 prevSegmentPolygonEndRight = QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3286 if ( cap != Qt::PenCapStyle::FlatCap )
3287 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3291 if ( i < inputPoints.size() - 1 )
3296 const QgsPoint startPointLeft = QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3297 const QgsPoint endPointLeft = QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3298 const QgsPoint startPointRight = QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3299 const QgsPoint endPointRight = QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3304 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3307 const QgsPoint nextSegmentStartPointLeft = QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3308 const QgsPoint nextSegmentEndPointLeft = QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3309 const QgsPoint nextSegmentStartPointRight = QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3310 const QgsPoint nextSegmentEndPointRight = QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3315 QgsPoint intersectionPoint;
3316 bool isIntersection =
false;
3318 if ( !isIntersection )
3319 thisSegmentPolygonEndLeft = endPointLeft;
3320 isIntersection =
false;
3321 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3322 if ( !isIntersection )
3323 thisSegmentPolygonEndRight = endPointRight;
3325 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3326 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3334 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3335 thisSegmentPolygonEndRight = startLinePolygonRight;
3337 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3338 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3342 thisSegmentPolygonEndLeft = QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3343 if ( cap != Qt::PenCapStyle::FlatCap )
3344 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3345 thisSegmentPolygonEndRight = QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3346 if ( cap != Qt::PenCapStyle::FlatCap )
3347 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3349 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3350 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3356 QTransform brushTransform;
3357 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3358 brushTransform.rotate( -segmentAngleDegrees );
3359 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3363 brushTransform.translate( -( lineThickness / 2 ), 0 );
3365 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3367 brush.setTransform( brushTransform );
3368 imagePainter.setBrush( brush );
3371 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3372 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3373 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3374 << prevSegmentPolygonEndRight.
toQPointF()
3375 << prevSegmentPolygonEndLeft.
toQPointF() );
3378 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3379 imagePainter.setBrush( Qt::NoBrush );
3380 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3381 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3382 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3383 << prevSegmentPolygonEndRight.
toQPointF()
3384 << prevSegmentPolygonEndLeft.
toQPointF() );
3385 imagePainter.setPen( Qt::NoPen );
3390 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3391 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3392 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3393 progressThroughImage = fmod( progressThroughImage, patternLength );
3396 segmentStartPoint = segmentEndPoint;
3397 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3398 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3406 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3407 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3424 auto res = std::make_unique<QgsRasterLineSymbolLayer>();
3426 if (
properties.contains( u
"line_width"_s ) )
3428 res->setWidth(
properties[u
"line_width"_s].toDouble() );
3430 if (
properties.contains( u
"line_width_unit"_s ) )
3434 if (
properties.contains( u
"width_map_unit_scale"_s ) )
3440 res->setPath(
properties[u
"imageFile"_s].toString() );
3444 res->setOffset(
properties[u
"offset"_s].toDouble() );
3446 if (
properties.contains( u
"offset_unit"_s ) )
3450 if (
properties.contains( u
"offset_map_unit_scale"_s ) )
3462 res->setOpacity(
properties[u
"alpha"_s].toDouble() );
3465 return res.release();
3472 map[u
"imageFile"_s] =
mPath;
3474 map[u
"line_width"_s] = QString::number(
mWidth );
3481 map[u
"offset"_s] = QString::number(
mOffset );
3485 map[u
"alpha"_s] = QString::number(
mOpacity );
3492 auto res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3503 return res.release();
3508 const QVariantMap::iterator it =
properties.find( u
"imageFile"_s );
3509 if ( it !=
properties.end() && it.value().userType() == QMetaType::Type::QString )
3525 return u
"RasterLine"_s;
3540 bool cached =
false;
3542 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3543 static_cast< int >( std::ceil( scaledHeight ) ) ),
3568 double strokeWidth =
mWidth;
3585 bool cached =
false;
3587 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3588 static_cast< int >( std::ceil( scaledHeight ) ) ),
3593 if ( useSelectedColor )
3598 const QBrush brush( sourceImage );
3668 auto res = std::make_unique<QgsLineburstSymbolLayer>();
3670 if (
properties.contains( u
"line_width"_s ) )
3672 res->setWidth(
properties[u
"line_width"_s].toDouble() );
3674 if (
properties.contains( u
"line_width_unit"_s ) )
3678 if (
properties.contains( u
"width_map_unit_scale"_s ) )
3685 res->setOffset(
properties[u
"offset"_s].toDouble() );
3687 if (
properties.contains( u
"offset_unit"_s ) )
3691 if (
properties.contains( u
"offset_map_unit_scale"_s ) )
3701 if (
properties.contains( u
"color_type"_s ) )
3708 if (
properties.contains( u
"gradient_color2"_s ) )
3723 return res.release();
3730 map[u
"line_width"_s] = QString::number(
mWidth );
3737 map[u
"offset"_s] = QString::number(
mOffset );
3754 auto res = std::make_unique< QgsLineburstSymbolLayer >();
3769 return res.release();
3774 return u
"Lineburst"_s;
3795 double strokeWidth =
mWidth;
3811 if ( useSelectedColor )
3815 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3826 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3838 gradient.setColorAt( 0.0, color1 );
3839 gradient.setColorAt( 1.0,
color2 );
3841 const QBrush brush( gradient );
3920 if ( props.contains( u
"line_width"_s ) )
3922 width = props[u
"line_width"_s].toDouble();
3924 else if ( props.contains( u
"outline_width"_s ) )
3926 width = props[u
"outline_width"_s].toDouble();
3928 else if ( props.contains( u
"width"_s ) )
3930 width = props[u
"width"_s].toDouble();
3935 if ( props.contains( u
"line_width_unit"_s ) )
3939 else if ( props.contains( u
"outline_width_unit"_s ) )
3943 else if ( props.contains( u
"width_unit"_s ) )
3948 if ( props.contains( u
"width_map_unit_scale"_s ) )
3950 if ( props.contains( u
"offset"_s ) )
3951 l->setOffset( props[u
"offset"_s].toDouble() );
3952 if ( props.contains( u
"offset_unit"_s ) )
3954 if ( props.contains( u
"offset_map_unit_scale"_s ) )
3956 if ( props.contains( u
"joinstyle"_s ) )
3958 if ( props.contains( u
"capstyle"_s ) )
3961 l->restoreOldDataDefinedProperties( props );
3968 return u
"FilledLine"_s;
4017 Qt::PenJoinStyle join = mPenJoinStyle;
4026 Qt::PenCapStyle cap = mPenCapStyle;
4042 const double prevOpacity = mFill->opacity();
4043 mFill->setOpacity( mFill->opacity() * context.
opacity() );
4050 if ( points.count() >= 2 )
4068 auto inputPoly = std::make_unique< QgsPolygon >(
static_cast< QgsLineString *
>( ls.release() ) );
4074 if ( !parts.empty() )
4102 std::unique_ptr< QgsAbstractGeometry > bufferedGeom =
QgsGeos::fromGeos( buffered.get() );
4104 for (
const QList< QPolygonF > &polygon : parts )
4106 QVector< QPolygonF > rings;
4107 for (
int i = 1; i < polygon.size(); ++i )
4108 rings << polygon.at( i );
4109 mFill->renderPolygon( polygon.value( 0 ), &rings, context.
feature(), context.
renderContext(), -1, useSelectedColor );
4117 mFill->setOpacity( prevOpacity );
4124 map[u
"line_width"_s] = QString::number(
mWidth );
4129 map[u
"offset"_s] = QString::number(
mOffset );
4143 res->setSubSymbol( mFill->clone() );
4144 return res.release();
4179 attr.unite( mFill->usedAttributes( context ) );
4187 if ( mFill && mFill->hasDataDefinedProperties() )
4196 mFill->setColor(
c );
4201 return mFill ? mFill->color() :
mColor;
4208 || ( mFill && mFill->usesMapUnits() );
4215 mFill->setMapUnitScale( scale );
4222 return mFill->mapUnitScale();
4231 mFill->setOutputUnit( unit );
4238 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(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
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)
void copyCommonProperties(QgsSymbolLayer *destLayer) const
Copies all common base class properties from this layer to another symbol layer.
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.
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.
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.