48#include <QDomDocument>
53using namespace Qt::StringLiterals;
60 mCustomDashVector << 5 << 2;
70 mCustomDashPatternUnit = unit;
71 mDashPatternOffsetUnit = unit;
72 mTrimDistanceStartUnit = unit;
73 mTrimDistanceEndUnit = unit;
96 mCustomDashPatternMapUnitScale = scale;
114 if ( props.contains( u
"line_color"_s ) )
118 else if ( props.contains( u
"outline_color"_s ) )
122 else if ( props.contains( u
"color"_s ) )
127 if ( props.contains( u
"line_width"_s ) )
129 width = props[u
"line_width"_s].toDouble();
131 else if ( props.contains( u
"outline_width"_s ) )
133 width = props[u
"outline_width"_s].toDouble();
135 else if ( props.contains( u
"width"_s ) )
138 width = props[u
"width"_s].toDouble();
140 if ( props.contains( u
"line_style"_s ) )
144 else if ( props.contains( u
"outline_style"_s ) )
148 else if ( props.contains( u
"penstyle"_s ) )
154 if ( props.contains( u
"line_width_unit"_s ) )
158 else if ( props.contains( u
"outline_width_unit"_s ) )
162 else if ( props.contains( u
"width_unit"_s ) )
167 if ( props.contains( u
"width_map_unit_scale"_s ) )
169 if ( props.contains( u
"offset"_s ) )
170 l->setOffset( props[u
"offset"_s].toDouble() );
171 if ( props.contains( u
"offset_unit"_s ) )
173 if ( props.contains( u
"offset_map_unit_scale"_s ) )
175 if ( props.contains( u
"joinstyle"_s ) )
177 if ( props.contains( u
"capstyle"_s ) )
180 if ( props.contains( u
"use_custom_dash"_s ) )
182 l->setUseCustomDashPattern( props[u
"use_custom_dash"_s].toInt() );
184 if ( props.contains( u
"customdash"_s ) )
188 if ( props.contains( u
"customdash_unit"_s ) )
192 if ( props.contains( u
"customdash_map_unit_scale"_s ) )
197 if ( props.contains( u
"draw_inside_polygon"_s ) )
199 l->setDrawInsidePolygon( props[u
"draw_inside_polygon"_s].toInt() );
202 if ( props.contains( u
"ring_filter"_s ) )
204 l->setRingFilter(
static_cast< RenderRingFilter>( props[u
"ring_filter"_s].toInt() ) );
207 if ( props.contains( u
"dash_pattern_offset"_s ) )
208 l->setDashPatternOffset( props[u
"dash_pattern_offset"_s].toDouble() );
209 if ( props.contains( u
"dash_pattern_offset_unit"_s ) )
211 if ( props.contains( u
"dash_pattern_offset_map_unit_scale"_s ) )
214 if ( props.contains( u
"trim_distance_start"_s ) )
215 l->setTrimDistanceStart( props[u
"trim_distance_start"_s].toDouble() );
216 if ( props.contains( u
"trim_distance_start_unit"_s ) )
218 if ( props.contains( u
"trim_distance_start_map_unit_scale"_s ) )
220 if ( props.contains( u
"trim_distance_end"_s ) )
221 l->setTrimDistanceEnd( props[u
"trim_distance_end"_s].toDouble() );
222 if ( props.contains( u
"trim_distance_end_unit"_s ) )
224 if ( props.contains( u
"trim_distance_end_map_unit_scale"_s ) )
227 if ( props.contains( u
"align_dash_pattern"_s ) )
228 l->setAlignDashPattern( props[u
"align_dash_pattern"_s].toInt() );
230 if ( props.contains( u
"tweak_dash_pattern_on_corners"_s ) )
231 l->setTweakDashPatternOnCorners( props[u
"tweak_dash_pattern_on_corners"_s].toInt() );
233 l->restoreOldDataDefinedProperties( props );
240 return u
"SimpleLine"_s;
252 mPen.setColor( penColor );
254 mPen.setWidthF( scaledWidth );
258 const double dashWidthDiv = std::max( 1.0, scaledWidth );
259 if ( mUseCustomDashPattern )
261 mPen.setStyle( Qt::CustomDashLine );
265 QVector<qreal> scaledVector;
266 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
267 for ( ; it != mCustomDashVector.constEnd(); ++it )
272 mPen.setDashPattern( scaledVector );
276 mPen.setStyle( mPenStyle );
279 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
284 mPen.setJoinStyle( mPenJoinStyle );
285 mPen.setCapStyle( mPenCapStyle );
290 selColor.setAlphaF( context.
opacity() );
291 mSelPen.setColor( selColor );
308 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
316 if ( mDrawInsidePolygon )
326 if ( mDrawInsidePolygon )
329 QPainterPath clipPath;
330 clipPath.addPolygon( points );
335 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
337 QPolygonF ring = *it;
338 clipPath.addPolygon( ring );
343 p->setClipPath( clipPath, Qt::IntersectClip );
366 for (
const QPolygonF &ring : std::as_const( *rings ) )
411 double totalLength = -1;
415 startTrim = startTrim * 0.01 * totalLength;
423 if ( totalLength < 0 )
425 endTrim = endTrim * 0.01 * totalLength;
446 QPolygonF points = pts;
447 trimPoints( points, mTrimDistanceStart, mTrimDistanceEnd, mTrimDistanceStartUnit, mTrimDistanceEndUnit, mTrimDistanceStartMapUnitScale, mTrimDistanceEndMapUnitScale,
mDataDefinedProperties, context );
451 mPen.setColor( penColor );
454 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
457 const QPen pen = useSelectedColor ? mSelPen : mPen;
459 if ( !pen.dashPattern().isEmpty() )
462 const QVector<double> pattern = pen.dashPattern();
463 bool foundNonNull =
false;
464 for (
int i = 0; i < pattern.size(); ++i )
476 p->setBrush( Qt::NoBrush );
480 if ( points.size() <= 2
483 && ( p->renderHints() & QPainter::Antialiasing ) )
486 p->setRenderHint( QPainter::Antialiasing,
false );
489 const bool applyPatternTweaks = mAlignDashPattern && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() ) && pen.dashOffset() == 0;
493 if ( applyPatternTweaks )
495 drawPathWithDashPatternTweaks( p, points, pen );
501 path.addPolygon( points );
517 for (
const QPolygonF &part : mline )
519 if ( applyPatternTweaks )
521 drawPathWithDashPatternTweaks( p, part, pen );
527 path.addPolygon( part );
538 map[u
"line_width"_s] = QString::number(
mWidth );
544 map[u
"offset"_s] = QString::number(
mOffset );
547 map[u
"use_custom_dash"_s] = ( mUseCustomDashPattern ? u
"1"_s : u
"0"_s );
551 map[u
"dash_pattern_offset"_s] = QString::number( mDashPatternOffset );
554 map[u
"trim_distance_start"_s] = QString::number( mTrimDistanceStart );
557 map[u
"trim_distance_end"_s] = QString::number( mTrimDistanceEnd );
560 map[u
"draw_inside_polygon"_s] = ( mDrawInsidePolygon ? u
"1"_s : u
"0"_s );
561 map[u
"ring_filter"_s] = QString::number(
static_cast< int >(
mRingFilter ) );
562 map[u
"align_dash_pattern"_s] = mAlignDashPattern ? u
"1"_s : u
"0"_s;
563 map[u
"tweak_dash_pattern_on_corners"_s] = mPatternCartographicTweakOnSharpCorners ? u
"1"_s : u
"0"_s;
603 toSld( doc, element, context );
608 if ( mPenStyle == Qt::NoPen )
612 QDomElement symbolizerElem = doc.createElement( u
"se:LineSymbolizer"_s );
613 if ( !props.value( u
"uom"_s, QString() ).toString().isEmpty() )
614 symbolizerElem.setAttribute( u
"uom"_s, props.value( u
"uom"_s, QString() ).toString() );
615 element.appendChild( symbolizerElem );
621 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
622 symbolizerElem.appendChild( strokeElem );
624 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
632 QDomElement perpOffsetElem = doc.createElement( u
"se:PerpendicularOffset"_s );
635 symbolizerElem.appendChild( perpOffsetElem );
642 if ( mUseCustomDashPattern )
656 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
657 if ( strokeElem.isNull() )
671 QDomElement perpOffsetElem = element.firstChildElement( u
"PerpendicularOffset"_s );
672 if ( !perpOffsetElem.isNull() )
675 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
680 double scaleFactor = 1.0;
681 const QString uom = element.attribute( u
"uom"_s );
687 l->setOutputUnit( sldUnitSize );
691 l->setUseCustomDashPattern(
penStyle == Qt::CustomDashLine );
696void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
702 bool hasStrokeWidthExpression =
false;
709 pen.setWidthF( scaledWidth );
710 selPen.setWidthF( scaledWidth );
711 hasStrokeWidthExpression =
true;
720 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
721 pen.setColor( penColor );
735 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
739 const QString customDashString
741 const QStringList dashList = customDashString.split(
';' );
742 QVector<qreal> dashVector;
743 for (
const QString &dash : dashList )
747 pen.setDashPattern( dashVector );
753 QVector<qreal> scaledVector;
754 for (
double v : std::as_const( mCustomDashVector ) )
759 mPen.setDashPattern( scaledVector );
763 double patternOffset = mDashPatternOffset;
775 const QString lineStyleString
784 const QString joinStyleString
793 const QString capStyleString
799void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
801 if ( pen.dashPattern().empty() || points.size() < 2 )
804 if ( pen.widthF() <= 1.0 )
806 pen.setWidthF( 1.0001 );
809 QVector< qreal > sourcePattern = pen.dashPattern();
810 const double dashWidthDiv = pen.widthF();
812 for (
int i = 0; i < sourcePattern.size(); ++i )
813 sourcePattern[i] *= pen.widthF();
815 QVector< qreal > buffer;
816 QPolygonF bufferedPoints;
817 QPolygonF previousSegmentBuffer;
822 auto ptIt = points.constBegin();
823 double totalBufferLength = 0;
824 int patternIndex = 0;
825 double currentRemainingDashLength = 0;
826 double currentRemainingGapLength = 0;
828 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal > {
829 QVector< qreal > result;
830 result.reserve( buffer.size() );
831 for (
auto it = buffer.begin(); it != buffer.end(); )
835 while ( dash == 0 && !result.empty() )
837 result.last() += gap;
839 if ( it == buffer.end() )
844 while ( gap == 0 && it != buffer.end() )
849 result << dash << gap;
854 double currentBufferLineLength = 0;
856 [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength, dashWidthDiv, &compressPattern](
859 if ( buffer.empty() || bufferedPoints.size() < 2 )
864 if ( currentRemainingDashLength )
867 buffer << currentRemainingDashLength << 0.0;
868 totalBufferLength += currentRemainingDashLength;
870 QVector< qreal > compressed = compressPattern( buffer );
871 if ( !currentRemainingDashLength )
874 totalBufferLength -= compressed.last();
875 compressed.last() = 0;
879 const double scaleFactor = currentBufferLineLength / totalBufferLength;
881 bool shouldFlushPreviousSegmentBuffer =
false;
883 if ( !previousSegmentBuffer.empty() )
887 if ( !firstDashSubstring.empty() )
893 compressed = compressed.mid( 2 );
894 shouldFlushPreviousSegmentBuffer = !compressed.empty();
897 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
899 QPen adjustedPen = pen;
900 adjustedPen.setStyle( Qt::SolidLine );
901 painter->setPen( adjustedPen );
903 path.addPolygon( previousSegmentBuffer );
904 painter->drawPath( path );
905 previousSegmentBuffer.clear();
908 double finalDash = 0;
915 if ( !compressed.empty() )
917 finalDash = compressed.at( compressed.size() - 2 );
918 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
920 const QPolygonF thisPoints = bufferedPoints;
926 previousSegmentBuffer << bufferedPoints;
930 currentBufferLineLength = 0;
931 currentRemainingDashLength = 0;
932 currentRemainingGapLength = 0;
933 totalBufferLength = 0;
936 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
938 QPen adjustedPen = pen;
939 if ( !compressed.empty() )
942 compressed = compressed.mid( 0, 32 );
943 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal &element ) { element *= scaleFactor / dashWidthDiv; } );
944 adjustedPen.setDashPattern( compressed );
948 adjustedPen.setStyle( Qt::SolidLine );
951 painter->setPen( adjustedPen );
953 path.addPolygon( bufferedPoints );
954 painter->drawPath( path );
957 bufferedPoints.clear();
963 bufferedPoints << p2;
964 for ( ; ptIt != points.constEnd(); ++ptIt )
972 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
973 currentBufferLineLength += remainingSegmentDistance;
977 if ( currentRemainingDashLength > 0 )
980 if ( remainingSegmentDistance >= currentRemainingDashLength )
983 buffer << currentRemainingDashLength << 0.0;
984 totalBufferLength += currentRemainingDashLength;
985 remainingSegmentDistance -= currentRemainingDashLength;
987 currentRemainingDashLength = 0.0;
988 currentRemainingGapLength = sourcePattern.at( patternIndex );
989 if ( currentRemainingGapLength == 0.0 )
997 buffer << remainingSegmentDistance << 0.0;
998 totalBufferLength += remainingSegmentDistance;
999 currentRemainingDashLength -= remainingSegmentDistance;
1003 if ( currentRemainingGapLength > 0 )
1006 if ( remainingSegmentDistance >= currentRemainingGapLength )
1009 buffer << 0.0 << currentRemainingGapLength;
1010 totalBufferLength += currentRemainingGapLength;
1011 remainingSegmentDistance -= currentRemainingGapLength;
1012 currentRemainingGapLength = 0.0;
1018 buffer << 0.0 << remainingSegmentDistance;
1019 totalBufferLength += remainingSegmentDistance;
1020 currentRemainingGapLength -= remainingSegmentDistance;
1025 if ( patternIndex + 1 >= sourcePattern.size() )
1030 const double nextPatternDashLength = sourcePattern.at( patternIndex );
1031 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
1032 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1034 buffer << nextPatternDashLength << nextPatternGapLength;
1035 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1036 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1039 else if ( nextPatternDashLength <= remainingSegmentDistance )
1042 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1043 totalBufferLength += remainingSegmentDistance;
1044 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1045 currentRemainingDashLength = 0;
1052 buffer << remainingSegmentDistance << 0.0;
1053 totalBufferLength += remainingSegmentDistance;
1054 currentRemainingGapLength = 0;
1055 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1060 bufferedPoints << p1;
1061 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1063 QPointF nextPoint = *( ptIt + 1 );
1069 flushBuffer( &nextPoint );
1070 bufferedPoints << p1;
1073 if ( patternIndex % 2 == 1 )
1077 currentRemainingDashLength = sourcePattern.at( patternIndex );
1084 flushBuffer(
nullptr );
1085 if ( !previousSegmentBuffer.empty() )
1087 QPen adjustedPen = pen;
1088 adjustedPen.setStyle( Qt::SolidLine );
1089 painter->setPen( adjustedPen );
1091 path.addPolygon( previousSegmentBuffer );
1092 painter->drawPath( path );
1093 previousSegmentBuffer.clear();
1099 if ( mDrawInsidePolygon )
1112 unit = mCustomDashPatternUnit;
1113 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1145 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1150 return mAlignDashPattern;
1160 return mPatternCartographicTweakOnSharpCorners;
1165 mPatternCartographicTweakOnSharpCorners =
enabled;
1186 : mRotateSymbols( rotateSymbol )
1222 if ( mRenderingFeature )
1226 mFeatureSymbolOpacity = context.
opacity();
1227 mCurrentFeatureIsSelected = useSelectedColor;
1245 QString placementString = exprVal.toString();
1246 if ( placementString.compare(
"interval"_L1, Qt::CaseInsensitive ) == 0 )
1250 else if ( placementString.compare(
"vertex"_L1, Qt::CaseInsensitive ) == 0 )
1254 else if ( placementString.compare(
"innervertices"_L1, Qt::CaseInsensitive ) == 0 )
1258 else if ( placementString.compare(
"lastvertex"_L1, Qt::CaseInsensitive ) == 0 )
1262 else if ( placementString.compare(
"firstvertex"_L1, Qt::CaseInsensitive ) == 0 )
1266 else if ( placementString.compare(
"centerpoint"_L1, Qt::CaseInsensitive ) == 0 )
1270 else if ( placementString.compare(
"curvepoint"_L1, Qt::CaseInsensitive ) == 0 )
1274 else if ( placementString.compare(
"segmentcenter"_L1, Qt::CaseInsensitive ) == 0 )
1287 double averageOver = mAverageAngleLength;
1295 QgsSymbolLayerUtils::BlankSegments blankSegments;
1300 QList<QList<QgsSymbolLayerUtils::BlankSegments>> allBlankSegments = QgsSymbolLayerUtils::parseBlankSegments( strBlankSegments, context.
renderContext(),
blankSegmentsUnit(), error );
1302 if ( !error.isEmpty() )
1304 QgsDebugError( u
"Badly formatted blank segment '%1', skip it: %2"_s.arg( strBlankSegments ).arg( error ) );
1310 if ( iPart >= 0 &&
mRingIndex >= 0 && iPart < allBlankSegments.count() &&
mRingIndex < allBlankSegments.at( iPart ).count() )
1312 blankSegments = allBlankSegments.at( iPart ).at(
mRingIndex );
1317 QPolygonF points = pts;
1318 trimPoints( points, mTrimDistanceStart, mTrimDistanceEnd, mTrimDistanceStartUnit, mTrimDistanceEndUnit, mTrimDistanceStartMapUnitScale, mTrimDistanceEndMapUnitScale,
mDataDefinedProperties, context );
1323 renderPolylineInterval( points, context, averageOver, blankSegments );
1325 renderPolylineCentral( points, context, averageOver, blankSegments );
1331 mHasRenderedFirstPart = mRenderingFeature;
1345 QList<QPolygonF> mline =
::
1348 for (
int part = 0; part < mline.count(); ++part )
1350 const QPolygonF &points2 = mline[part];
1353 renderPolylineInterval( points2, context, averageOver, blankSegments );
1355 renderPolylineCentral( points2, context, averageOver, blankSegments );
1365 mHasRenderedFirstPart = mRenderingFeature;
1374 QgsSymbolLayerUtils::ExtraItems extraItems;
1379 extraItems = QgsSymbolLayerUtils::parseExtraItems( strExtraItems, error );
1381 if ( !error.isEmpty() )
1383 QgsDebugError( u
"Badly formatted extra items '%1', skip it: %2"_s.arg( strExtraItems ).arg( error ) );
1388 for ( std::pair<QPointF, double> &extraItem : extraItems )
1410 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1426 mBlockExtraItemsRendering =
true;
1441 for (
int i = 0; i < rings->size(); ++i )
1452 mBlockExtraItemsRendering =
true;
1463 mBlockExtraItemsRendering =
false;
1479 mIntervalUnit = unit;
1480 mOffsetAlongLineUnit = unit;
1481 mAverageAngleLengthUnit = unit;
1505 map[u
"interval"_s] = QString::number(
interval() );
1506 map[u
"offset"_s] = QString::number(
mOffset );
1514 map[u
"average_angle_length"_s] = QString::number( mAverageAngleLength );
1517 map[u
"trim_distance_start"_s] = QString::number( mTrimDistanceStart );
1520 map[u
"trim_distance_end"_s] = QString::number( mTrimDistanceEnd );
1527 map[u
"ring_filter"_s] = QString::number(
static_cast< int >(
mRingFilter ) );
1528 map[u
"place_on_every_part"_s] = mPlaceOnEveryPart;
1534 return mPlaceOnEveryPart
1544 mRenderingFeature =
true;
1545 mHasRenderedFirstPart =
false;
1550 mRenderingFeature =
false;
1561 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1562 mFeatureSymbolOpacity = 1;
1602 if (
properties.contains( u
"offset_unit"_s ) )
1606 if (
properties.contains( u
"interval_unit"_s ) )
1610 if (
properties.contains( u
"offset_along_line"_s ) )
1614 if (
properties.contains( u
"offset_along_line_unit"_s ) )
1618 if (
properties.contains( ( u
"offset_along_line_map_unit_scale"_s ) ) )
1623 if (
properties.contains( u
"offset_map_unit_scale"_s ) )
1627 if (
properties.contains( u
"interval_map_unit_scale"_s ) )
1632 if (
properties.contains( u
"average_angle_length"_s ) )
1636 if (
properties.contains( u
"average_angle_unit"_s ) )
1640 if (
properties.contains( ( u
"average_angle_map_unit_scale"_s ) ) )
1644 if (
properties.contains( u
"blank_segments_unit"_s ) )
1649 if (
properties.contains( u
"trim_distance_start"_s ) )
1651 if (
properties.contains( u
"trim_distance_start_unit"_s ) )
1653 if (
properties.contains( u
"trim_distance_start_map_unit_scale"_s ) )
1655 if (
properties.contains( u
"trim_distance_end"_s ) )
1657 if (
properties.contains( u
"trim_distance_end_unit"_s ) )
1659 if (
properties.contains( u
"trim_distance_end_map_unit_scale"_s ) )
1664 if (
properties[u
"placement"_s] ==
"vertex"_L1 )
1666 else if (
properties[u
"placement"_s] ==
"lastvertex"_L1 )
1668 else if (
properties[u
"placement"_s] ==
"firstvertex"_L1 )
1670 else if (
properties[u
"placement"_s] ==
"centralpoint"_L1 )
1672 else if (
properties[u
"placement"_s] ==
"curvepoint"_L1 )
1674 else if (
properties[u
"placement"_s] ==
"segmentcenter"_L1 )
1679 else if (
properties.contains( u
"placements"_s ) )
1685 if (
properties.contains( u
"ring_filter"_s ) )
1701class BlankSegmentsWalker
1704 BlankSegmentsWalker(
const QPolygonF &points,
const QgsSymbolLayerUtils::BlankSegments &blankSegments )
1705 : mBlankSegments( blankSegments )
1707 , mItBlankSegment( blankSegments.cbegin() )
1709 mDistances.reserve( mPoints.count() );
1713 bool insideBlankSegment(
double distance )
1715 while ( mItBlankSegment != mBlankSegments.cend() && distance > mItBlankSegment->second )
1720 return ( mItBlankSegment != mBlankSegments.cend() && distance >= mItBlankSegment->first );
1725 bool insideBlankSegment(
const QPointF &point,
int pointIndex )
1727 if ( pointIndex < 0 || pointIndex >= mPoints.count() )
1731 if ( pointIndex >= mDistances.count() )
1733 for (
int i =
static_cast<int>( mDistances.count() ); i < pointIndex + 1; i++ )
1735 const QPointF diff = mPoints.at( i ) - mPoints.at( i - 1 );
1736 const double distance = std::sqrt( std::pow( diff.x(), 2 ) + std::pow( diff.y(), 2 ) );
1737 const double totalDistance = distance + mDistances.last();
1738 mDistances << totalDistance;
1742 const QPointF diff = mPoints.at( pointIndex ) - point;
1743 const double distance = std::sqrt( std::pow( diff.x(), 2 ) + std::pow( diff.y(), 2 ) );
1744 const double currentDistance = mDistances.at( pointIndex ) + distance;
1746 return insideBlankSegment( currentDistance );
1750 const QgsSymbolLayerUtils::BlankSegments &mBlankSegments;
1751 const QPolygonF &mPoints;
1752 QList<double> mDistances;
1753 QgsSymbolLayerUtils::BlankSegments::const_iterator mItBlankSegment;
1760void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver,
const QgsSymbolLayerUtils::BlankSegments &blankSegments )
1762 if ( points.isEmpty() )
1766 double lengthLeft = 0;
1771 QgsExpressionContextScope *scope =
new QgsExpressionContextScope();
1798 constexpr double EPSILON = 1e-5;
1799 if ( painterUnitInterval <
EPSILON )
1802 double painterUnitOffsetAlongLine = 0;
1805 double totalLength = -1;
1826 if ( points.isClosed() )
1828 if ( painterUnitOffsetAlongLine > 0 )
1830 if ( totalLength < 0 )
1832 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1834 else if ( painterUnitOffsetAlongLine < 0 )
1836 if ( totalLength < 0 )
1838 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1850 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1852 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1854 QVector< QPointF > angleStartPoints;
1855 QVector< QPointF > symbolPoints;
1856 QVector< QPointF > angleEndPoints;
1865 QList<int> pointIndices;
1866 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft, blankSegments.isEmpty() ?
nullptr : &pointIndices );
1868 if ( symbolPoints.empty() )
1874 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1877 symbolPoints.pop_back();
1880 angleEndPoints.reserve( symbolPoints.size() );
1881 angleStartPoints.reserve( symbolPoints.size() );
1882 if ( averageOver <= painterUnitOffsetAlongLine )
1884 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver,
nullptr, 0, symbolPoints.size() );
1888 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0,
nullptr, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1890 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver,
nullptr, 0, symbolPoints.size() );
1893 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
1894 for (
int i = 0; i < symbolPoints.size(); ++i )
1899 const QPointF pt = symbolPoints[i];
1900 if ( i < pointIndices.count() && blankSegmentsWalker.insideBlankSegment( pt, pointIndices.at( i ) ) )
1904 const QPointF startPt = angleStartPoints[i];
1905 const QPointF endPt = angleEndPoints[i];
1907 Line l( startPt, endPt );
1922 QPointF lastPt = points[0];
1923 BlankSegmentsWalker itBlankSegment( points, blankSegments );
1924 for (
int i = 1; i < points.count(); ++i )
1929 const QPointF &pt = points[i];
1935 Line l( lastPt, pt );
1936 QPointF diff = l.diffForInterval( painterUnitInterval );
1941 double c = 1 - lengthLeft / painterUnitInterval;
1943 lengthLeft += l.length();
1952 while ( lengthLeft > painterUnitInterval )
1959 if ( !itBlankSegment.insideBlankSegment( lastPt, i - 1 ) )
1965 lengthLeft -= painterUnitInterval;
1973static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1976 double a1 = Line( prevPt, pt ).angle();
1977 double a2 = Line( pt, nextPt ).angle();
1978 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1980 return std::atan2( unitY, unitX );
1983void QgsTemplatedLineSymbolLayerBase::renderPolylineVertex(
1987 if ( points.isEmpty() )
1992 int i = -1, maxCount = 0;
1993 bool isRing =
false;
1995 QgsExpressionContextScope *scope =
new QgsExpressionContextScope();
2007 double totalLength = -1;
2027 if ( points.isClosed() )
2031 if ( totalLength < 0 )
2037 if ( totalLength < 0 )
2111 i = points.count() - 1;
2113 maxCount = points.count();
2121 maxCount = points.count() - 1;
2129 maxCount = points.count();
2130 if ( points.first() == points.last() )
2147 renderOffsetVertexAlongLine( points, i, distance, context,
placement, blankSegments );
2154 prevPoint = points.at( 0 );
2156 QPointF symbolPoint;
2157 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
2158 for ( ; i < maxCount; ++i )
2169 QPointF currentPoint = points.at( i );
2170 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ), 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2173 double angle = std::atan2( currentPoint.y() - prevPoint.y(), currentPoint.x() - prevPoint.x() );
2176 prevPoint = currentPoint;
2180 symbolPoint = points.at( i );
2184 double angle = markerAngle( points, isRing, i );
2189 mFinalVertex = symbolPoint;
2195double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2198 const QPointF &pt = points[vertex];
2200 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2202 int prevIndex = vertex - 1;
2203 int nextIndex = vertex + 1;
2205 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2207 prevIndex = points.count() - 2;
2211 QPointF prevPoint, nextPoint;
2212 while ( prevIndex >= 0 )
2214 prevPoint = points[prevIndex];
2215 if ( prevPoint != pt )
2222 while ( nextIndex < points.count() )
2224 nextPoint = points[nextIndex];
2225 if ( nextPoint != pt )
2232 if ( prevIndex >= 0 && nextIndex < points.count() )
2234 angle = _averageAngle( prevPoint, pt, nextPoint );
2241 while ( vertex < points.size() - 1 )
2243 const QPointF &nextPt = points[vertex + 1];
2246 angle = Line( pt, nextPt ).angle();
2255 while ( vertex >= 1 )
2257 const QPointF &prevPt = points[vertex - 1];
2260 angle = Line( prevPt, pt ).angle();
2270void QgsTemplatedLineSymbolLayerBase::renderOffsetVertexAlongLine(
2274 if ( points.isEmpty() )
2284 bool isRing =
false;
2285 if ( points.first() == points.last() )
2287 double angle = markerAngle( points, isRing, vertex );
2290 mFinalVertex = points[vertex];
2296 int pointIncrement = distance > 0 ? 1 : -1;
2297 QPointF previousPoint = points[vertex];
2298 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2299 int endPoint = distance > 0 ? points.count() - 1 : 0;
2300 double distanceLeft = std::fabs( distance );
2301 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
2303 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2305 const QPointF &pt = points[i];
2307 if ( previousPoint == pt )
2311 Line l( previousPoint, pt );
2313 if ( distanceLeft < l.length() )
2316 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2322 mFinalVertex = markerPoint;
2328 distanceLeft -= l.length();
2335void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
2336 const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset, QList<int> *pointIndices,
double initialLag,
int numberPointsRequired
2342 QVector< QPointF > points = p;
2343 const bool closedRing = points.first() == points.last();
2345 double lengthLeft = initialOffset;
2347 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2348 if ( initialLagLeft < 0 && closedRing )
2351 QPointF lastPt = points.constLast();
2352 QVector< QPointF > pseudoPoints;
2353 for (
int i = points.count() - 2; i > 0; --i )
2355 if ( initialLagLeft >= 0 )
2360 const QPointF &pt = points[i];
2365 Line l( lastPt, pt );
2366 initialLagLeft += l.length();
2371 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2373 points = pseudoPoints;
2378 while ( initialLagLeft < 0 )
2380 dest << points.constFirst();
2381 initialLagLeft += intervalPainterUnits;
2384 if ( initialLag > 0 )
2386 lengthLeft += intervalPainterUnits - initialLagLeft;
2389 QPointF lastPt = points[0];
2390 for (
int i = 1; i < points.count(); ++i )
2392 const QPointF &pt = points[i];
2396 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2405 Line l( lastPt, pt );
2406 QPointF diff = l.diffForInterval( intervalPainterUnits );
2410 double c = 1 - lengthLeft / intervalPainterUnits;
2412 lengthLeft += l.length();
2415 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2419 lengthLeft -= intervalPainterUnits;
2422 *pointIndices << i - 1;
2425 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2430 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2434 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2441 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2444 while ( dest.size() < numberPointsRequired )
2445 dest << points.constLast();
2449void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver,
const QgsSymbolLayerUtils::BlankSegments &blankSegments )
2451 if ( !points.isEmpty() )
2455 QPolygonF::const_iterator it = points.constBegin();
2457 for ( ++it; it != points.constEnd(); ++it )
2459 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) + ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2465 const double midPoint = length / 2;
2467 BlankSegmentsWalker blankSegmentsWalker( points, blankSegments );
2468 if ( blankSegmentsWalker.insideBlankSegment( midPoint ) )
2472 double thisSymbolAngle = 0;
2474 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2476 QVector< QPointF > angleStartPoints;
2477 QVector< QPointF > symbolPoints;
2478 QVector< QPointF > angleEndPoints;
2482 collectOffsetPoints( points, symbolPoints, midPoint, midPoint,
nullptr, 0.0, 2 );
2483 collectOffsetPoints( points, angleStartPoints, midPoint, 0,
nullptr, averageAngleOver, 2 );
2484 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver,
nullptr, 0, 2 );
2486 pt = symbolPoints.at( 1 );
2487 Line l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2488 thisSymbolAngle = l.angle();
2493 it = points.constBegin();
2495 qreal last_at = 0, next_at = 0;
2497 for ( ++it; it != points.constEnd(); ++it )
2500 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) + ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2501 if ( next_at >= midPoint )
2508 Line l( last, next );
2509 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2510 pt = last + ( next - last ) * k;
2511 thisSymbolAngle = l.angle();
2562 if ( props.contains( u
"interval"_s ) )
2563 interval = props[u
"interval"_s].toDouble();
2564 if ( props.contains( u
"rotate"_s ) )
2565 rotate = ( props[u
"rotate"_s].toString() ==
"1"_L1 );
2567 auto x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2574 return u
"MarkerLine"_s;
2594 mMarker->setRenderHints( hints );
2616 toSld( doc, element, context );
2622 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2624 QDomElement symbolizerElem = doc.createElement( u
"se:LineSymbolizer"_s );
2625 if ( !props.value( u
"uom"_s, QString() ).toString().isEmpty() )
2626 symbolizerElem.setAttribute( u
"uom"_s, props.value( u
"uom"_s, QString() ).toString() );
2627 element.appendChild( symbolizerElem );
2657 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
2658 symbolizerElem.appendChild( strokeElem );
2661 QDomElement graphicStrokeElem = doc.createElement( u
"se:GraphicStroke"_s );
2662 strokeElem.appendChild( graphicStrokeElem );
2667 markerLayer->writeSldMarker( doc, graphicStrokeElem, context );
2675 QgsDebugError( u
"Missing marker line symbol layer. Skip it."_s );
2678 if ( !gap.isEmpty() )
2680 QDomElement gapElem = doc.createElement( u
"se:Gap"_s );
2682 graphicStrokeElem.appendChild( gapElem );
2687 QDomElement perpOffsetElem = doc.createElement( u
"se:PerpendicularOffset"_s );
2690 symbolizerElem.appendChild( perpOffsetElem );
2700 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
2701 if ( strokeElem.isNull() )
2704 QDomElement graphicStrokeElem = strokeElem.firstChildElement( u
"GraphicStroke"_s );
2705 if ( graphicStrokeElem.isNull() )
2713 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2715 if ( it.key() ==
"placement"_L1 )
2717 if ( it.value() ==
"points"_L1 )
2719 else if ( it.value() ==
"firstPoint"_L1 )
2721 else if ( it.value() ==
"lastPoint"_L1 )
2723 else if ( it.value() ==
"centralPoint"_L1 )
2726 else if ( it.value() ==
"rotateMarker"_L1 )
2732 std::unique_ptr< QgsMarkerSymbol > marker;
2738 layers.append( l.release() );
2739 marker = std::make_unique<QgsMarkerSymbol>( layers );
2746 QDomElement gapElem = graphicStrokeElem.firstChildElement( u
"Gap"_s );
2747 if ( !gapElem.isNull() )
2750 double d = gapElem.firstChild().firstChild().nodeValue().toDouble( &ok );
2756 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( u
"PerpendicularOffset"_s );
2757 if ( !perpOffsetElem.isNull() )
2760 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2765 double scaleFactor = 1.0;
2766 const QString uom = element.attribute( u
"uom"_s );
2771 auto x = std::make_unique<QgsMarkerLineSymbolLayer>(
rotateMarker );
2772 x->setOutputUnit( sldUnitSize );
2775 x->setSubSymbol( marker.release() );
2789 mMarker->setDataDefinedSize( property );
2796 const double prevOpacity =
mMarker->opacity();
2799 mMarker->setOpacity( prevOpacity );
2804 mMarker->setLineAngle( angle );
2822 mMarker->renderPoint( point, feature, context, layer, selected );
2834 return mMarker->size( context );
2840 mMarker->setOutputUnit( unit );
2863 attr.unite(
mMarker->usedAttributes( context ) );
2899 if ( props.contains( u
"interval"_s ) )
2900 interval = props[u
"interval"_s].toDouble();
2901 if ( props.contains( u
"rotate"_s ) )
2902 rotate = ( props[u
"rotate"_s] ==
"1"_L1 );
2904 auto x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2906 if ( props.contains( u
"hash_angle"_s ) )
2908 x->setHashAngle( props[u
"hash_angle"_s].toDouble() );
2911 if ( props.contains( u
"hash_length"_s ) )
2912 x->setHashLength( props[u
"hash_length"_s].toDouble() );
2914 if ( props.contains( u
"hash_length_unit"_s ) )
2917 if ( props.contains( u
"hash_length_map_unit_scale"_s ) )
2925 return u
"HashLine"_s;
2934 mHashSymbol->setRenderHints( hints );
2947 map[u
"hash_angle"_s] = QString::number( mHashAngle );
2949 map[u
"hash_length"_s] = QString::number( mHashLength );
2960 x->setHashAngle( mHashAngle );
2961 x->setHashLength( mHashLength );
2962 x->setHashLengthUnit( mHashLengthUnit );
2963 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2969 mHashSymbol->setColor(
color );
2975 return mHashSymbol ? mHashSymbol->color() :
mColor;
2980 return mHashSymbol.get();
2991 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2992 mColor = mHashSymbol->color();
2998 mHashLength =
width;
3013 return ( mHashSymbol->width( context ) / 2.0 )
3021 mHashSymbol->setOutputUnit( unit );
3028 attr.unite( mHashSymbol->usedAttributes( context ) );
3036 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
3045 mHashSymbol->setDataDefinedWidth( property );
3065 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
3070 mSymbolLineAngle = angle;
3075 return mSymbolAngle;
3080 mSymbolAngle = angle;
3085 double lineLength = mHashLength;
3091 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
3105 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
3110 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
3127 const double prevOpacity = mHashSymbol->opacity();
3128 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
3130 mHashSymbol->setOpacity( prevOpacity );
3149 QPolygonF offsetPoints;
3152 renderLine( points, context, patternThickness, patternLength, brush );
3161 renderLine( part, context, patternThickness, patternLength, brush );
3166void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
const double patternLength,
const QBrush &sourceBrush )
3172 QBrush brush = sourceBrush;
3177 QPolygonF inputPoints;
3178 inputPoints.reserve( points.size() );
3180 double minX = std::numeric_limits< double >::max();
3181 double minY = std::numeric_limits< double >::max();
3182 double maxX = std::numeric_limits< double >::lowest();
3183 double maxY = std::numeric_limits< double >::lowest();
3185 for (
const QPointF &pt : std::as_const( points ) )
3192 minX = std::min( minX, pt.x() );
3193 minY = std::min( minY, pt.y() );
3194 maxX = std::max( maxX, pt.x() );
3195 maxY = std::max( maxY, pt.y() );
3198 if ( inputPoints.size() < 2 )
3202 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3204 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3207 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3208 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3210 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 ) &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3212 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3213 if ( temporaryImage.isNull() )
3222 temporaryImage.fill( Qt::transparent );
3245 QPainterPathStroker stroker;
3246 stroker.setWidth( lineThickness );
3247 stroker.setCapStyle( cap );
3248 stroker.setJoinStyle( join );
3251 path.addPolygon( inputPoints );
3252 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3255 QPainter imagePainter;
3256 imagePainter.begin( &temporaryImage );
3258 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3260 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3261 imagePainter.setPen( Qt::NoPen );
3263 QPointF segmentStartPoint = inputPoints.at( 0 );
3266 double progressThroughImage = 0;
3268 QgsPoint prevSegmentPolygonEndLeft;
3269 QgsPoint prevSegmentPolygonEndRight;
3272 QgsPoint startLinePolygonLeft;
3273 QgsPoint startLinePolygonRight;
3275 for (
int i = 1; i < inputPoints.size(); ++i )
3280 const QPointF segmentEndPoint = inputPoints.at( i );
3281 const double segmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtilsBase::lineAngle( segmentStartPoint.x(), segmentStartPoint.y(), segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3284 QgsPoint thisSegmentPolygonEndLeft;
3285 QgsPoint thisSegmentPolygonEndRight;
3287 QgsPoint thisSegmentPolygonEndLeftForPainter;
3288 QgsPoint thisSegmentPolygonEndRightForPainter;
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 );
3303 const double lastSegmentAngleDegrees = 180.0
3305 *
QgsGeometryUtilsBase::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(), segmentStartPoint.x(), segmentStartPoint.y() )
3309 const QgsPoint lastSegmentStartPointLeft = QgsPoint( points.at( points.size() - 2 ) ).project( lineThickness / 2, lastSegmentAngleDegrees );
3310 const QgsPoint lastSegmentEndPointLeft = QgsPoint( segmentStartPoint ).project( lineThickness / 2, lastSegmentAngleDegrees );
3311 const QgsPoint lastSegmentStartPointRight = QgsPoint( points.at( points.size() - 2 ) ).project( -lineThickness / 2, lastSegmentAngleDegrees );
3312 const QgsPoint lastSegmentEndPointRight = QgsPoint( segmentStartPoint ).project( -lineThickness / 2, lastSegmentAngleDegrees );
3317 QgsPoint intersectionPoint;
3318 bool isIntersection =
false;
3320 if ( !isIntersection )
3321 prevSegmentPolygonEndLeft = startPointLeft;
3322 isIntersection =
false;
3323 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3324 if ( !isIntersection )
3325 prevSegmentPolygonEndRight = startPointRight;
3327 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3328 startLinePolygonRight = prevSegmentPolygonEndRight;
3332 prevSegmentPolygonEndLeft = QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3333 if ( cap != Qt::PenCapStyle::FlatCap )
3334 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3335 prevSegmentPolygonEndRight = QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3336 if ( cap != Qt::PenCapStyle::FlatCap )
3337 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3341 if ( i < inputPoints.size() - 1 )
3346 const QgsPoint startPointLeft = QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3347 const QgsPoint endPointLeft = QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3348 const QgsPoint startPointRight = QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3349 const QgsPoint endPointRight = QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3353 const double nextSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtilsBase::lineAngle( segmentEndPoint.x(), segmentEndPoint.y(), inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3356 const QgsPoint nextSegmentStartPointLeft = QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3357 const QgsPoint nextSegmentEndPointLeft = QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3358 const QgsPoint nextSegmentStartPointRight = QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3359 const QgsPoint nextSegmentEndPointRight = QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3364 QgsPoint intersectionPoint;
3365 bool isIntersection =
false;
3367 if ( !isIntersection )
3368 thisSegmentPolygonEndLeft = endPointLeft;
3369 isIntersection =
false;
3370 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3371 if ( !isIntersection )
3372 thisSegmentPolygonEndRight = endPointRight;
3374 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3375 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3383 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3384 thisSegmentPolygonEndRight = startLinePolygonRight;
3386 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3387 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3391 thisSegmentPolygonEndLeft = QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3392 if ( cap != Qt::PenCapStyle::FlatCap )
3393 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3394 thisSegmentPolygonEndRight = QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3395 if ( cap != Qt::PenCapStyle::FlatCap )
3396 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3398 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3399 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3405 QTransform brushTransform;
3406 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3407 brushTransform.rotate( -segmentAngleDegrees );
3408 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3412 brushTransform.translate( -( lineThickness / 2 ), 0 );
3414 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3416 brush.setTransform( brushTransform );
3417 imagePainter.setBrush( brush );
3420 imagePainter.drawPolygon(
3422 << prevSegmentPolygonEndLeft.
toQPointF()
3423 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3424 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3425 << prevSegmentPolygonEndRight.
toQPointF()
3426 << prevSegmentPolygonEndLeft.
toQPointF()
3430 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3431 imagePainter.setBrush( Qt::NoBrush );
3432 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3433 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3434 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3435 << prevSegmentPolygonEndRight.
toQPointF()
3436 << prevSegmentPolygonEndLeft.
toQPointF() );
3437 imagePainter.setPen( Qt::NoPen );
3442 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 ) + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3443 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3444 progressThroughImage = fmod( progressThroughImage, patternLength );
3447 segmentStartPoint = segmentEndPoint;
3448 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3449 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3457 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS, minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3473 auto res = std::make_unique<QgsRasterLineSymbolLayer>();
3475 if (
properties.contains( u
"line_width"_s ) )
3477 res->setWidth(
properties[u
"line_width"_s].toDouble() );
3479 if (
properties.contains( u
"line_width_unit"_s ) )
3483 if (
properties.contains( u
"width_map_unit_scale"_s ) )
3489 res->setPath(
properties[u
"imageFile"_s].toString() );
3493 res->setOffset(
properties[u
"offset"_s].toDouble() );
3495 if (
properties.contains( u
"offset_unit"_s ) )
3499 if (
properties.contains( u
"offset_map_unit_scale"_s ) )
3511 res->setOpacity(
properties[u
"alpha"_s].toDouble() );
3521 map[u
"imageFile"_s] =
mPath;
3523 map[u
"line_width"_s] = QString::number(
mWidth );
3530 map[u
"offset"_s] = QString::number(
mOffset );
3534 map[u
"alpha"_s] = QString::number(
mOpacity );
3541 auto res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3552 return res.release();
3557 const QVariantMap::iterator it =
properties.find( u
"imageFile"_s );
3558 if ( it !=
properties.end() && it.value().userType() == QMetaType::Type::QString )
3574 return u
"RasterLine"_s;
3589 bool cached =
false;
3592 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
static_cast< int >( std::ceil( scaledHeight ) ) ),
3620 double strokeWidth =
mWidth;
3637 bool cached =
false;
3640 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
static_cast< int >( std::ceil( scaledHeight ) ) ),
3649 if ( useSelectedColor )
3654 const QBrush brush( sourceImage );
3722 auto res = std::make_unique<QgsLineburstSymbolLayer>();
3724 if (
properties.contains( u
"line_width"_s ) )
3726 res->setWidth(
properties[u
"line_width"_s].toDouble() );
3728 if (
properties.contains( u
"line_width_unit"_s ) )
3732 if (
properties.contains( u
"width_map_unit_scale"_s ) )
3739 res->setOffset(
properties[u
"offset"_s].toDouble() );
3741 if (
properties.contains( u
"offset_unit"_s ) )
3745 if (
properties.contains( u
"offset_map_unit_scale"_s ) )
3755 if (
properties.contains( u
"color_type"_s ) )
3762 if (
properties.contains( u
"gradient_color2"_s ) )
3784 map[u
"line_width"_s] = QString::number(
mWidth );
3791 map[u
"offset"_s] = QString::number(
mOffset );
3808 auto res = std::make_unique< QgsLineburstSymbolLayer >();
3823 return res.release();
3828 return u
"Lineburst"_s;
3847 double strokeWidth =
mWidth;
3863 if ( useSelectedColor )
3867 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3878 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3891 gradient.setColorAt( 0.0, color1 );
3892 gradient.setColorAt( 1.0,
color2 );
3894 const QBrush brush( gradient );
3971 if ( props.contains( u
"line_width"_s ) )
3973 width = props[u
"line_width"_s].toDouble();
3975 else if ( props.contains( u
"outline_width"_s ) )
3977 width = props[u
"outline_width"_s].toDouble();
3979 else if ( props.contains( u
"width"_s ) )
3981 width = props[u
"width"_s].toDouble();
3986 if ( props.contains( u
"line_width_unit"_s ) )
3990 else if ( props.contains( u
"outline_width_unit"_s ) )
3994 else if ( props.contains( u
"width_unit"_s ) )
3999 if ( props.contains( u
"width_map_unit_scale"_s ) )
4001 if ( props.contains( u
"offset"_s ) )
4002 l->setOffset( props[u
"offset"_s].toDouble() );
4003 if ( props.contains( u
"offset_unit"_s ) )
4005 if ( props.contains( u
"offset_map_unit_scale"_s ) )
4007 if ( props.contains( u
"joinstyle"_s ) )
4009 if ( props.contains( u
"capstyle"_s ) )
4012 l->restoreOldDataDefinedProperties( props );
4019 return u
"FilledLine"_s;
4068 Qt::PenJoinStyle join = mPenJoinStyle;
4077 Qt::PenCapStyle cap = mPenCapStyle;
4093 const double prevOpacity = mFill->opacity();
4094 mFill->setOpacity( mFill->opacity() * context.
opacity() );
4101 if ( points.count() >= 2 )
4120 auto inputPoly = std::make_unique< QgsPolygon >(
static_cast< QgsLineString *
>( ls.release() ) );
4126 if ( !parts.empty() )
4153 std::unique_ptr< QgsAbstractGeometry > bufferedGeom =
QgsGeos::fromGeos( buffered.get() );
4155 for (
const QList< QPolygonF > &polygon : parts )
4157 QVector< QPolygonF > rings;
4158 for (
int i = 1; i < polygon.size(); ++i )
4159 rings << polygon.at( i );
4160 mFill->renderPolygon( polygon.value( 0 ), &rings, context.
feature(), context.
renderContext(), -1, useSelectedColor );
4168 mFill->setOpacity( prevOpacity );
4175 map[u
"line_width"_s] = QString::number(
mWidth );
4180 map[u
"offset"_s] = QString::number(
mOffset );
4194 res->setSubSymbol( mFill->clone() );
4195 return res.release();
4230 attr.unite( mFill->usedAttributes( context ) );
4238 if ( mFill && mFill->hasDataDefinedProperties() )
4247 mFill->setColor(
c );
4252 return mFill ? mFill->color() :
mColor;
4261 || ( mFill && mFill->usesMapUnits() );
4268 mFill->setMapUnitScale( scale );
4275 return mFill->mapUnitScale();
4284 mFill->setOutputUnit( unit );
4291 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.
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 QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
static std::unique_ptr< QgsColorRamp > create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
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.
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.
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.
static std::unique_ptr< QgsSymbolLayer > create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFilledLineSymbolLayer, using the settings serialized in the properties map (correspo...
~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 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 geos::unique_ptr offsetCurve(const GEOSGeometry *geometry, double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg=nullptr, QgsFeedback *feedback=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, QgsFeedback *feedback=nullptr) const override
Buffers the geometry.
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 std::unique_ptr< 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.
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.
static std::unique_ptr< QgsSymbolLayer > create(const QVariantMap &properties=QVariantMap())
Creates a new QgsHashedLineSymbolLayer, using the settings serialized in the properties map (correspo...
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.
static std::unique_ptr< QgsSymbolLayer > create(const QVariantMap &properties=QVariantMap())
Creates a new QgsLineburstSymbolLayer, using the settings serialized in the properties map (correspon...
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...
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QgsLineburstSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, const QColor &color2=Qt::white)
Constructor for QgsLineburstSymbolLayer, with the specified start and end gradient colors.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsColorRamp * colorRamp()
Returns the color ramp used for the gradient line.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
Perform transforms between map coordinates and device coordinates.
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.
static std::unique_ptr< QgsSymbolLayer > createFromSld(QDomElement &element)
Creates a new QgsMarkerLineSymbolLayer from an SLD XML DOM element.
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.
static std::unique_ptr< QgsSymbolLayer > create(const QVariantMap &properties=QVariantMap())
Creates a new QgsMarkerLineSymbolLayer, using the settings serialized in the properties map (correspo...
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.
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.
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 ...
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
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.
static std::unique_ptr< QgsSymbolLayer > create(const QVariantMap &properties=QVariantMap())
Creates a new QgsRasterLineSymbolLayer, 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.
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 ...
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 convertToMapUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to map units.
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.
@ NoSave
Do not save the current painter state.
void save()
Performs a manual save on the painter state, pushing another saved state to the painter.
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
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.
double dxfWidth(QgsSymbolRenderContext &context) const override
Gets line width.
double dxfOffset(QgsSymbolRenderContext &context) const override
Gets offset.
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...
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...
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.
static std::unique_ptr< QgsSymbolLayer > create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
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.
static std::unique_ptr< QgsSymbolLayer > createFromSld(QDomElement &element)
Creates a new QgsSimpleLineSymbolLayer from an SLD XML DOM element.
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)
Lossy-encodes a color to a string.
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.
@ ExtraItems
String list of tuple (x, y and rotation angle) to define extra items to be rendered for templated lin...
@ 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.
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 setTrimDistanceStartMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the start of the line.
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...
void renderPolyline(const QPolygonF &pts, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
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.
void setTrimDistanceEndMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the end of the line.
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
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 setTrimDistanceStartUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the start of the line.
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.
void setTrimDistanceStart(double distance)
Sets the trim distance for the start of the line, which dictates a length from the start of the line ...
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.
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...
const QgsMapUnitScale & offsetAlongLineMapUnitScale() const
Returns the map unit scale used for calculating the offset in map units along line for symbols.
void setTrimDistanceEndUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the end of the line.
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
void trimPoints(QPolygonF &points, double startTrim, double endTrim, Qgis::RenderUnit trimDistanceStartUnit, Qgis::RenderUnit trimDistanceEndUnit, const QgsMapUnitScale &trimDistanceStartMapUnitScale, const QgsMapUnitScale &trimDistanceEndMapUnitScale, const QgsPropertyCollection &mDataDefinedProperties, QgsSymbolRenderContext &context)
trim points according to start and end trim distance based on data defined properties and render cont...
#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.