39#include <QDomDocument>
45 : mPenStyle( penStyle )
49 mCustomDashVector << 5 << 2;
59 mCustomDashPatternUnit = unit;
60 mDashPatternOffsetUnit = unit;
61 mTrimDistanceStartUnit = unit;
62 mTrimDistanceEndUnit = unit;
86 mCustomDashPatternMapUnitScale = scale;
106 if ( props.contains( QStringLiteral(
"line_color" ) ) )
110 else if ( props.contains( QStringLiteral(
"outline_color" ) ) )
114 else if ( props.contains( QStringLiteral(
"color" ) ) )
119 if ( props.contains( QStringLiteral(
"line_width" ) ) )
121 width = props[QStringLiteral(
"line_width" )].toDouble();
123 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
125 width = props[QStringLiteral(
"outline_width" )].toDouble();
127 else if ( props.contains( QStringLiteral(
"width" ) ) )
130 width = props[QStringLiteral(
"width" )].toDouble();
132 if ( props.contains( QStringLiteral(
"line_style" ) ) )
136 else if ( props.contains( QStringLiteral(
"outline_style" ) ) )
140 else if ( props.contains( QStringLiteral(
"penstyle" ) ) )
146 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
150 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
154 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
159 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
161 if ( props.contains( QStringLiteral(
"offset" ) ) )
162 l->
setOffset( props[QStringLiteral(
"offset" )].toDouble() );
163 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
165 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
167 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
169 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
172 if ( props.contains( QStringLiteral(
"use_custom_dash" ) ) )
176 if ( props.contains( QStringLiteral(
"customdash" ) ) )
180 if ( props.contains( QStringLiteral(
"customdash_unit" ) ) )
184 if ( props.contains( QStringLiteral(
"customdash_map_unit_scale" ) ) )
189 if ( props.contains( QStringLiteral(
"draw_inside_polygon" ) ) )
194 if ( props.contains( QStringLiteral(
"ring_filter" ) ) )
199 if ( props.contains( QStringLiteral(
"dash_pattern_offset" ) ) )
201 if ( props.contains( QStringLiteral(
"dash_pattern_offset_unit" ) ) )
203 if ( props.contains( QStringLiteral(
"dash_pattern_offset_map_unit_scale" ) ) )
206 if ( props.contains( QStringLiteral(
"trim_distance_start" ) ) )
208 if ( props.contains( QStringLiteral(
"trim_distance_start_unit" ) ) )
210 if ( props.contains( QStringLiteral(
"trim_distance_start_map_unit_scale" ) ) )
212 if ( props.contains( QStringLiteral(
"trim_distance_end" ) ) )
214 if ( props.contains( QStringLiteral(
"trim_distance_end_unit" ) ) )
216 if ( props.contains( QStringLiteral(
"trim_distance_end_map_unit_scale" ) ) )
219 if ( props.contains( QStringLiteral(
"align_dash_pattern" ) ) )
222 if ( props.contains( QStringLiteral(
"tweak_dash_pattern_on_corners" ) ) )
232 return QStringLiteral(
"SimpleLine" );
239 mPen.setColor( penColor );
241 mPen.setWidthF( scaledWidth );
245 const double dashWidthDiv = std::max( 1.0, scaledWidth );
246 if ( mUseCustomDashPattern )
248 mPen.setStyle( Qt::CustomDashLine );
252 QVector<qreal> scaledVector;
253 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
254 for ( ; it != mCustomDashVector.constEnd(); ++it )
259 mPen.setDashPattern( scaledVector );
263 mPen.setStyle( mPenStyle );
266 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
271 mPen.setJoinStyle( mPenJoinStyle );
272 mPen.setCapStyle( mPenCapStyle );
277 selColor.setAlphaF( context.
opacity() );
278 mSelPen.setColor( selColor );
295 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
302 if ( mDrawInsidePolygon )
310 if ( mDrawInsidePolygon )
313 QPainterPath clipPath;
314 clipPath.addPolygon( points );
319 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
321 QPolygonF ring = *it;
322 clipPath.addPolygon( ring );
327 p->setClipPath( clipPath, Qt::IntersectClip );
350 for (
const QPolygonF &ring : std::as_const( *rings ) )
366 if ( mDrawInsidePolygon )
382 QPolygonF points = pts;
384 double startTrim = mTrimDistanceStart;
390 double endTrim = mTrimDistanceEnd;
397 double totalLength = -1;
401 startTrim = startTrim * 0.01 * totalLength;
409 if ( totalLength < 0 )
411 endTrim = endTrim * 0.01 * totalLength;
424 mPen.setColor( penColor );
427 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
430 const QPen pen = useSelectedColor ? mSelPen : mPen;
432 if ( !pen.dashPattern().isEmpty() )
435 const QVector<double> pattern = pen.dashPattern();
436 bool foundNonNull =
false;
437 for (
int i = 0; i < pattern.size(); ++i )
449 p->setBrush( Qt::NoBrush );
452 std::unique_ptr< QgsScopedQPainterState > painterState;
453 if ( points.size() <= 2 &&
456 ( p->renderHints() & QPainter::Antialiasing ) )
458 painterState = std::make_unique< QgsScopedQPainterState >( p );
459 p->setRenderHint( QPainter::Antialiasing,
false );
462 const bool applyPatternTweaks = mAlignDashPattern
463 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
464 && pen.dashOffset() == 0;
468 if ( applyPatternTweaks )
470 drawPathWithDashPatternTweaks( p, points, pen );
476 path.addPolygon( points );
491 for (
const QPolygonF &part : mline )
493 if ( applyPatternTweaks )
495 drawPathWithDashPatternTweaks( p, part, pen );
501 path.addPolygon( part );
512 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
518 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
521 map[QStringLiteral(
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
525 map[QStringLiteral(
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
528 map[QStringLiteral(
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
531 map[QStringLiteral(
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
534 map[QStringLiteral(
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
535 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
536 map[QStringLiteral(
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
537 map[QStringLiteral(
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
576 if ( mPenStyle == Qt::NoPen )
579 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
580 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
581 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
582 element.appendChild( symbolizerElem );
588 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
589 symbolizerElem.appendChild( strokeElem );
591 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
600 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
603 symbolizerElem.appendChild( perpOffsetElem );
609 if ( mUseCustomDashPattern )
612 mPen.color(), mPenJoinStyle,
613 mPenCapStyle,
mOffset, &mCustomDashVector );
626 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
627 if ( strokeElem.isNull() )
644 QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
645 if ( !perpOffsetElem.isNull() )
648 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
653 double scaleFactor = 1.0;
654 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
669void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
675 bool hasStrokeWidthExpression =
false;
682 pen.setWidthF( scaledWidth );
683 selPen.setWidthF( scaledWidth );
684 hasStrokeWidthExpression =
true;
693 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
694 pen.setColor( penColor );
708 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
712 QVector<qreal> dashVector;
716 QStringList dashList = exprVal.toString().split(
';' );
717 QStringList::const_iterator dashIt = dashList.constBegin();
718 for ( ; dashIt != dashList.constEnd(); ++dashIt )
722 pen.setDashPattern( dashVector );
729 QVector<qreal> scaledVector;
730 for (
double v : std::as_const( mCustomDashVector ) )
735 mPen.setDashPattern( scaledVector );
739 double patternOffset = mDashPatternOffset;
775void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
777 if ( pen.dashPattern().empty() || points.size() < 2 )
780 if ( pen.widthF() <= 1.0 )
782 pen.setWidthF( 1.0001 );
785 QVector< qreal > sourcePattern = pen.dashPattern();
786 const double dashWidthDiv = pen.widthF();
788 for (
int i = 0; i < sourcePattern.size(); ++ i )
789 sourcePattern[i] *= pen.widthF();
791 QVector< qreal > buffer;
792 QPolygonF bufferedPoints;
793 QPolygonF previousSegmentBuffer;
798 auto ptIt = points.constBegin();
799 double totalBufferLength = 0;
800 int patternIndex = 0;
801 double currentRemainingDashLength = 0;
802 double currentRemainingGapLength = 0;
804 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
806 QVector< qreal > result;
807 result.reserve( buffer.size() );
808 for (
auto it = buffer.begin(); it != buffer.end(); )
812 while ( dash == 0 && !result.empty() )
814 result.last() += gap;
816 if ( it == buffer.end() )
821 while ( gap == 0 && it != buffer.end() )
826 result << dash << gap;
831 double currentBufferLineLength = 0;
832 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
833 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
835 if ( buffer.empty() || bufferedPoints.size() < 2 )
840 if ( currentRemainingDashLength )
843 buffer << currentRemainingDashLength << 0.0;
844 totalBufferLength += currentRemainingDashLength;
846 QVector< qreal > compressed = compressPattern( buffer );
847 if ( !currentRemainingDashLength )
850 totalBufferLength -= compressed.last();
851 compressed.last() = 0;
855 const double scaleFactor = currentBufferLineLength / totalBufferLength;
857 bool shouldFlushPreviousSegmentBuffer =
false;
859 if ( !previousSegmentBuffer.empty() )
863 if ( !firstDashSubstring.empty() )
869 compressed = compressed.mid( 2 );
870 shouldFlushPreviousSegmentBuffer = !compressed.empty();
873 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
875 QPen adjustedPen = pen;
876 adjustedPen.setStyle( Qt::SolidLine );
877 painter->setPen( adjustedPen );
879 path.addPolygon( previousSegmentBuffer );
880 painter->drawPath( path );
881 previousSegmentBuffer.clear();
884 double finalDash = 0;
891 if ( !compressed.empty() )
893 finalDash = compressed.at( compressed.size() - 2 );
894 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
896 const QPolygonF thisPoints = bufferedPoints;
902 previousSegmentBuffer << bufferedPoints;
906 currentBufferLineLength = 0;
907 currentRemainingDashLength = 0;
908 currentRemainingGapLength = 0;
909 totalBufferLength = 0;
912 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
914 QPen adjustedPen = pen;
915 if ( !compressed.empty() )
918 compressed = compressed.mid( 0, 32 );
919 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
920 adjustedPen.setDashPattern( compressed );
924 adjustedPen.setStyle( Qt::SolidLine );
927 painter->setPen( adjustedPen );
929 path.addPolygon( bufferedPoints );
930 painter->drawPath( path );
933 bufferedPoints.clear();
939 bufferedPoints << p2;
940 for ( ; ptIt != points.constEnd(); ++ptIt )
948 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
949 currentBufferLineLength += remainingSegmentDistance;
953 if ( currentRemainingDashLength > 0 )
956 if ( remainingSegmentDistance >= currentRemainingDashLength )
959 buffer << currentRemainingDashLength << 0.0;
960 totalBufferLength += currentRemainingDashLength;
961 remainingSegmentDistance -= currentRemainingDashLength;
963 currentRemainingDashLength = 0.0;
964 currentRemainingGapLength = sourcePattern.at( patternIndex );
965 if ( currentRemainingGapLength == 0.0 )
973 buffer << remainingSegmentDistance << 0.0;
974 totalBufferLength += remainingSegmentDistance;
975 currentRemainingDashLength -= remainingSegmentDistance;
979 if ( currentRemainingGapLength > 0 )
982 if ( remainingSegmentDistance >= currentRemainingGapLength )
985 buffer << 0.0 << currentRemainingGapLength;
986 totalBufferLength += currentRemainingGapLength;
987 remainingSegmentDistance -= currentRemainingGapLength;
988 currentRemainingGapLength = 0.0;
994 buffer << 0.0 << remainingSegmentDistance;
995 totalBufferLength += remainingSegmentDistance;
996 currentRemainingGapLength -= remainingSegmentDistance;
1001 if ( patternIndex + 1 >= sourcePattern.size() )
1006 const double nextPatternDashLength = sourcePattern.at( patternIndex );
1007 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
1008 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1010 buffer << nextPatternDashLength << nextPatternGapLength;
1011 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1012 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1015 else if ( nextPatternDashLength <= remainingSegmentDistance )
1018 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1019 totalBufferLength += remainingSegmentDistance;
1020 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1021 currentRemainingDashLength = 0;
1028 buffer << remainingSegmentDistance << 0.0;
1029 totalBufferLength += remainingSegmentDistance;
1030 currentRemainingGapLength = 0;
1031 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1036 bufferedPoints << p1;
1037 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1039 QPointF nextPoint = *( ptIt + 1 );
1045 flushBuffer( &nextPoint );
1046 bufferedPoints << p1;
1049 if ( patternIndex % 2 == 1 )
1053 currentRemainingDashLength = sourcePattern.at( patternIndex );
1060 flushBuffer(
nullptr );
1061 if ( !previousSegmentBuffer.empty() )
1063 QPen adjustedPen = pen;
1064 adjustedPen.setStyle( Qt::SolidLine );
1065 painter->setPen( adjustedPen );
1067 path.addPolygon( previousSegmentBuffer );
1068 painter->drawPath( path );
1069 previousSegmentBuffer.clear();
1075 if ( mDrawInsidePolygon )
1089 unit = mCustomDashPatternUnit;
1090 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1127 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1132 return mAlignDashPattern;
1142 return mPatternCartographicTweakOnSharpCorners;
1147 mPatternCartographicTweakOnSharpCorners =
enabled;
1175 MyLine( QPointF p1, QPointF p2 )
1176 : mVertical( false )
1177 , mIncreasing( false )
1189 mIncreasing = ( p2.y() > p1.y() );
1194 mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
1195 mIncreasing = ( p2.x() > p1.x() );
1199 double x = ( p2.x() - p1.x() );
1200 double y = ( p2.y() - p1.y() );
1201 mLength = std::sqrt( x * x + y * y );
1207 double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
1215 QPointF diffForInterval(
double interval )
1218 return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
1220 double alpha = std::atan( mT );
1221 double dx = std::cos( alpha ) * interval;
1222 double dy = std::sin( alpha ) * interval;
1223 return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
1226 double length()
const {
return mLength; }
1241 : mRotateSymbols( rotateSymbol )
1242 , mInterval( interval )
1281 if ( mRenderingFeature )
1285 mFeatureSymbolOpacity = context.
opacity();
1286 mCurrentFeatureIsSelected = useSelectedColor;
1304 QString placementString = exprVal.toString();
1305 if ( placementString.compare( QLatin1String(
"interval" ), Qt::CaseInsensitive ) == 0 )
1309 else if ( placementString.compare( QLatin1String(
"vertex" ), Qt::CaseInsensitive ) == 0 )
1313 else if ( placementString.compare( QLatin1String(
"innervertices" ), Qt::CaseInsensitive ) == 0 )
1317 else if ( placementString.compare( QLatin1String(
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
1321 else if ( placementString.compare( QLatin1String(
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
1325 else if ( placementString.compare( QLatin1String(
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
1329 else if ( placementString.compare( QLatin1String(
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
1333 else if ( placementString.compare( QLatin1String(
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
1346 double averageOver = mAverageAngleLength;
1357 renderPolylineInterval( points, context, averageOver );
1359 renderPolylineCentral( points, context, averageOver );
1363 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1366 mHasRenderedFirstPart = mRenderingFeature;
1382 for (
int part = 0; part < mline.count(); ++part )
1384 const QPolygonF &points2 = mline[ part ];
1387 renderPolylineInterval( points2, context, averageOver );
1389 renderPolylineCentral( points2, context, averageOver );
1397 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1400 mHasRenderedFirstPart = mRenderingFeature;
1420 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1450 for (
int i = 0; i < rings->size(); ++i )
1483 mIntervalUnit = unit;
1484 mOffsetAlongLineUnit = unit;
1485 mAverageAngleLengthUnit = unit;
1510 map[QStringLiteral(
"rotate" )] = (
rotateSymbols() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1511 map[QStringLiteral(
"interval" )] = QString::number(
interval() );
1512 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
1513 map[QStringLiteral(
"offset_along_line" )] = QString::number(
offsetAlongLine() );
1520 map[QStringLiteral(
"average_angle_length" )] = QString::number( mAverageAngleLength );
1526 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
1527 map[QStringLiteral(
"place_on_every_part" )] = mPlaceOnEveryPart;
1533 return mPlaceOnEveryPart
1541 mRenderingFeature =
true;
1542 mHasRenderedFirstPart =
false;
1547 mRenderingFeature =
false;
1555 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1556 mFeatureSymbolOpacity = 1;
1583 if (
properties.contains( QStringLiteral(
"offset" ) ) )
1587 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
1591 if (
properties.contains( QStringLiteral(
"interval_unit" ) ) )
1595 if (
properties.contains( QStringLiteral(
"offset_along_line" ) ) )
1599 if (
properties.contains( QStringLiteral(
"offset_along_line_unit" ) ) )
1603 if (
properties.contains( ( QStringLiteral(
"offset_along_line_map_unit_scale" ) ) ) )
1608 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1612 if (
properties.contains( QStringLiteral(
"interval_map_unit_scale" ) ) )
1617 if (
properties.contains( QStringLiteral(
"average_angle_length" ) ) )
1621 if (
properties.contains( QStringLiteral(
"average_angle_unit" ) ) )
1625 if (
properties.contains( ( QStringLiteral(
"average_angle_map_unit_scale" ) ) ) )
1630 if (
properties.contains( QStringLiteral(
"placement" ) ) )
1632 if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"vertex" ) )
1634 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"lastvertex" ) )
1636 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"firstvertex" ) )
1638 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"centralpoint" ) )
1640 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"curvepoint" ) )
1642 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"segmentcenter" ) )
1647 else if (
properties.contains( QStringLiteral(
"placements" ) ) )
1653 if (
properties.contains( QStringLiteral(
"ring_filter" ) ) )
1663void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver )
1665 if ( points.isEmpty() )
1669 double lengthLeft = 0;
1701 if ( painterUnitInterval < 0 )
1704 double painterUnitOffsetAlongLine = 0;
1707 double totalLength = -1;
1728 if ( points.isClosed() )
1730 if ( painterUnitOffsetAlongLine > 0 )
1732 if ( totalLength < 0 )
1734 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1736 else if ( painterUnitOffsetAlongLine < 0 )
1738 if ( totalLength < 0 )
1740 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1752 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1754 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1756 QVector< QPointF > angleStartPoints;
1757 QVector< QPointF > symbolPoints;
1758 QVector< QPointF > angleEndPoints;
1766 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
1768 if ( symbolPoints.empty() )
1774 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1777 symbolPoints.pop_back();
1780 angleEndPoints.reserve( symbolPoints.size() );
1781 angleStartPoints.reserve( symbolPoints.size() );
1782 if ( averageOver <= painterUnitOffsetAlongLine )
1784 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
1788 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1790 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
1793 for (
int i = 0; i < symbolPoints.size(); ++ i )
1798 const QPointF pt = symbolPoints[i];
1799 const QPointF startPt = angleStartPoints[i];
1800 const QPointF endPt = angleEndPoints[i];
1802 MyLine l( startPt, endPt );
1817 QPointF lastPt = points[0];
1818 for (
int i = 1; i < points.count(); ++i )
1823 const QPointF &pt = points[i];
1829 MyLine l( lastPt, pt );
1830 QPointF diff = l.diffForInterval( painterUnitInterval );
1834 double c = 1 - lengthLeft / painterUnitInterval;
1836 lengthLeft += l.length();
1845 while ( lengthLeft > painterUnitInterval )
1849 lengthLeft -= painterUnitInterval;
1861static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1864 double a1 = MyLine( prevPt, pt ).angle();
1865 double a2 = MyLine( pt, nextPt ).angle();
1866 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1868 return std::atan2( unitY, unitX );
1873 if ( points.isEmpty() )
1878 int i = -1, maxCount = 0;
1879 bool isRing =
false;
1893 double totalLength = -1;
1913 if ( points.isClosed() )
1917 if ( totalLength < 0 )
1923 if ( totalLength < 0 )
1997 i = points.count() - 1;
1999 maxCount = points.count();
2007 maxCount = points.count() - 1;
2015 maxCount = points.count();
2016 if ( points.first() == points.last() )
2033 renderOffsetVertexAlongLine( points, i, distance, context,
placement );
2040 prevPoint = points.at( 0 );
2042 QPointF symbolPoint;
2043 for ( ; i < maxCount; ++i )
2054 QPointF currentPoint = points.at( i );
2055 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2056 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2059 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2060 currentPoint.x() - prevPoint.x() );
2063 prevPoint = currentPoint;
2067 symbolPoint = points.at( i );
2071 double angle = markerAngle( points, isRing, i );
2076 mFinalVertex = symbolPoint;
2082double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2085 const QPointF &pt = points[vertex];
2087 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2089 int prevIndex = vertex - 1;
2090 int nextIndex = vertex + 1;
2092 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2094 prevIndex = points.count() - 2;
2098 QPointF prevPoint, nextPoint;
2099 while ( prevIndex >= 0 )
2101 prevPoint = points[ prevIndex ];
2102 if ( prevPoint != pt )
2109 while ( nextIndex < points.count() )
2111 nextPoint = points[ nextIndex ];
2112 if ( nextPoint != pt )
2119 if ( prevIndex >= 0 && nextIndex < points.count() )
2121 angle = _averageAngle( prevPoint, pt, nextPoint );
2128 while ( vertex < points.size() - 1 )
2130 const QPointF &nextPt = points[vertex + 1];
2133 angle = MyLine( pt, nextPt ).angle();
2142 while ( vertex >= 1 )
2144 const QPointF &prevPt = points[vertex - 1];
2147 angle = MyLine( prevPt, pt ).angle();
2159 if ( points.isEmpty() )
2169 bool isRing =
false;
2170 if ( points.first() == points.last() )
2172 double angle = markerAngle( points, isRing, vertex );
2175 mFinalVertex = points[vertex];
2181 int pointIncrement = distance > 0 ? 1 : -1;
2182 QPointF previousPoint = points[vertex];
2183 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2184 int endPoint = distance > 0 ? points.count() - 1 : 0;
2185 double distanceLeft = std::fabs( distance );
2187 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2189 const QPointF &pt = points[i];
2191 if ( previousPoint == pt )
2195 MyLine l( previousPoint, pt );
2197 if ( distanceLeft < l.length() )
2200 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2206 mFinalVertex = markerPoint;
2212 distanceLeft -= l.length();
2219void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
double initialLag,
int numberPointsRequired )
2224 QVector< QPointF > points = p;
2225 const bool closedRing = points.first() == points.last();
2227 double lengthLeft = initialOffset;
2229 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2230 if ( initialLagLeft < 0 && closedRing )
2233 QPointF lastPt = points.constLast();
2234 QVector< QPointF > pseudoPoints;
2235 for (
int i = points.count() - 2; i > 0; --i )
2237 if ( initialLagLeft >= 0 )
2242 const QPointF &pt = points[i];
2247 MyLine l( lastPt, pt );
2248 initialLagLeft += l.length();
2253 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2255 points = pseudoPoints;
2260 while ( initialLagLeft < 0 )
2262 dest << points.constFirst();
2263 initialLagLeft += intervalPainterUnits;
2266 if ( initialLag > 0 )
2268 lengthLeft += intervalPainterUnits - initialLagLeft;
2271 QPointF lastPt = points[0];
2272 for (
int i = 1; i < points.count(); ++i )
2274 const QPointF &pt = points[i];
2278 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2287 MyLine l( lastPt, pt );
2288 QPointF diff = l.diffForInterval( intervalPainterUnits );
2292 double c = 1 - lengthLeft / intervalPainterUnits;
2294 lengthLeft += l.length();
2297 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2301 lengthLeft -= intervalPainterUnits;
2304 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2309 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2313 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2320 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2323 while ( dest.size() < numberPointsRequired )
2324 dest << points.constLast();
2328void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver )
2330 if ( !points.isEmpty() )
2334 QPolygonF::const_iterator it = points.constBegin();
2336 for ( ++it; it != points.constEnd(); ++it )
2338 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2339 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2345 const double midPoint = length / 2;
2348 double thisSymbolAngle = 0;
2350 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2352 QVector< QPointF > angleStartPoints;
2353 QVector< QPointF > symbolPoints;
2354 QVector< QPointF > angleEndPoints;
2356 collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
2357 collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
2358 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
2360 pt = symbolPoints.at( 1 );
2361 MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2362 thisSymbolAngle = l.angle();
2367 it = points.constBegin();
2369 qreal last_at = 0, next_at = 0;
2371 for ( ++it; it != points.constEnd(); ++it )
2374 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2375 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2376 if ( next_at >= midPoint )
2383 MyLine l( last, next );
2384 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2385 pt = last + ( next - last ) * k;
2386 thisSymbolAngle = l.angle();
2438 if ( props.contains( QStringLiteral(
"interval" ) ) )
2439 interval = props[QStringLiteral(
"interval" )].toDouble();
2440 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2441 rotate = ( props[QStringLiteral(
"rotate" )].toString() == QLatin1String(
"1" ) );
2443 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2450 return QStringLiteral(
"MarkerLine" );
2467 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2470 mMarker->setRenderHints( hints );
2483 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >(
rotateSymbols(),
interval() );
2490 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2492 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
2493 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2494 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2495 element.appendChild( symbolizerElem );
2525 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2526 symbolizerElem.appendChild( strokeElem );
2529 QDomElement graphicStrokeElem = doc.createElement( QStringLiteral(
"se:GraphicStroke" ) );
2530 strokeElem.appendChild( graphicStrokeElem );
2535 markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
2539 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) ) );
2543 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"Missing marker line symbol layer. Skip it." ) ) );
2546 if ( !gap.isEmpty() )
2548 QDomElement gapElem = doc.createElement( QStringLiteral(
"se:Gap" ) );
2550 graphicStrokeElem.appendChild( gapElem );
2555 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
2558 symbolizerElem.appendChild( perpOffsetElem );
2567 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2568 if ( strokeElem.isNull() )
2571 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
2572 if ( graphicStrokeElem.isNull() )
2580 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2582 if ( it.key() == QLatin1String(
"placement" ) )
2584 if ( it.value() == QLatin1String(
"points" ) )
2586 else if ( it.value() == QLatin1String(
"firstPoint" ) )
2588 else if ( it.value() == QLatin1String(
"lastPoint" ) )
2590 else if ( it.value() == QLatin1String(
"centralPoint" ) )
2593 else if ( it.value() == QLatin1String(
"rotateMarker" ) )
2599 std::unique_ptr< QgsMarkerSymbol > marker;
2613 QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"Gap" ) );
2614 if ( !gapElem.isNull() )
2617 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
2623 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
2624 if ( !perpOffsetElem.isNull() )
2627 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2632 double scaleFactor = 1.0;
2633 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
2656 mMarker->setDataDefinedSize( property );
2663 const double prevOpacity =
mMarker->opacity();
2666 mMarker->setOpacity( prevOpacity );
2671 mMarker->setLineAngle( angle );
2689 mMarker->renderPoint( point, feature, context, layer, selected );
2701 return mMarker->size( context );
2707 mMarker->setOutputUnit( unit );
2724 attr.unite(
mMarker->usedAttributes( context ) );
2739 return (
mMarker->size( context ) / 2.0 ) +
2761 if ( props.contains( QStringLiteral(
"interval" ) ) )
2762 interval = props[QStringLiteral(
"interval" )].toDouble();
2763 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2764 rotate = ( props[QStringLiteral(
"rotate" )] == QLatin1String(
"1" ) );
2766 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2768 if ( props.contains( QStringLiteral(
"hash_angle" ) ) )
2770 x->setHashAngle( props[QStringLiteral(
"hash_angle" )].toDouble() );
2773 if ( props.contains( QStringLiteral(
"hash_length" ) ) )
2774 x->setHashLength( props[QStringLiteral(
"hash_length" )].toDouble() );
2776 if ( props.contains( QStringLiteral(
"hash_length_unit" ) ) )
2779 if ( props.contains( QStringLiteral(
"hash_length_map_unit_scale" ) ) )
2787 return QStringLiteral(
"HashLine" );
2793 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2796 mHashSymbol->setRenderHints( hints );
2809 map[ QStringLiteral(
"hash_angle" ) ] = QString::number( mHashAngle );
2811 map[QStringLiteral(
"hash_length" )] = QString::number( mHashLength );
2820 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >(
rotateSymbols(),
interval() );
2822 x->setHashAngle( mHashAngle );
2823 x->setHashLength( mHashLength );
2824 x->setHashLengthUnit( mHashLengthUnit );
2825 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2831 mHashSymbol->setColor(
color );
2837 return mHashSymbol ? mHashSymbol->color() :
mColor;
2842 return mHashSymbol.get();
2853 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2854 mColor = mHashSymbol->color();
2860 mHashLength =
width;
2875 return ( mHashSymbol->width( context ) / 2.0 )
2883 mHashSymbol->setOutputUnit( unit );
2890 attr.unite( mHashSymbol->usedAttributes( context ) );
2898 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
2907 mHashSymbol->setDataDefinedWidth( property );
2920 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
2925 mSymbolLineAngle = angle;
2930 return mSymbolAngle;
2935 mSymbolAngle = angle;
2940 double lineLength = mHashLength;
2946 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
2960 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
2965 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
2982 const double prevOpacity = mHashSymbol->opacity();
2983 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
2985 mHashSymbol->setOpacity( prevOpacity );
3004 QPolygonF offsetPoints;
3007 renderLine( points, context, patternThickness, patternLength, brush );
3016 renderLine( part, context, patternThickness, patternLength, brush );
3021void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3022 const double patternLength,
const QBrush &sourceBrush )
3028 QBrush brush = sourceBrush;
3033 QPolygonF inputPoints;
3034 inputPoints.reserve( points.size() );
3036 double minX = std::numeric_limits< double >::max();
3037 double minY = std::numeric_limits< double >::max();
3038 double maxX = std::numeric_limits< double >::lowest();
3039 double maxY = std::numeric_limits< double >::lowest();
3041 for (
const QPointF &pt : std::as_const( points ) )
3048 minX = std::min( minX, pt.x() );
3049 minY = std::min( minY, pt.y() );
3050 maxX = std::max( maxX, pt.x() );
3051 maxY = std::max( maxY, pt.y() );
3054 if ( inputPoints.size() < 2 )
3058 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3060 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3063 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3064 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3066 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3067 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3069 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3070 if ( temporaryImage.isNull() )
3079 temporaryImage.fill( Qt::transparent );
3102 QPainterPathStroker stroker;
3103 stroker.setWidth( lineThickness );
3104 stroker.setCapStyle( cap );
3105 stroker.setJoinStyle( join );
3108 path.addPolygon( inputPoints );
3109 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3112 QPainter imagePainter;
3113 imagePainter.begin( &temporaryImage );
3115 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3117 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3118 imagePainter.setPen( Qt::NoPen );
3120 QPointF segmentStartPoint = inputPoints.at( 0 );
3123 double progressThroughImage = 0;
3125 QgsPoint prevSegmentPolygonEndLeft;
3126 QgsPoint prevSegmentPolygonEndRight;
3132 for (
int i = 1; i < inputPoints.size(); ++i )
3137 const QPointF segmentEndPoint = inputPoints.at( i );
3139 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3142 QgsPoint thisSegmentPolygonEndLeft;
3143 QgsPoint thisSegmentPolygonEndRight;
3145 QgsPoint thisSegmentPolygonEndLeftForPainter;
3146 QgsPoint thisSegmentPolygonEndRightForPainter;
3154 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3156 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3157 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3161 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtilsBase::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3162 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3165 const QgsPoint lastSegmentStartPointLeft =
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3166 const QgsPoint lastSegmentEndPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3167 const QgsPoint lastSegmentStartPointRight =
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3168 const QgsPoint lastSegmentEndPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3174 bool isIntersection =
false;
3176 if ( !isIntersection )
3177 prevSegmentPolygonEndLeft = startPointLeft;
3178 isIntersection =
false;
3179 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3180 if ( !isIntersection )
3181 prevSegmentPolygonEndRight = startPointRight;
3183 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3184 startLinePolygonRight = prevSegmentPolygonEndRight;
3188 prevSegmentPolygonEndLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3189 if ( cap != Qt::PenCapStyle::FlatCap )
3190 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3191 prevSegmentPolygonEndRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3192 if ( cap != Qt::PenCapStyle::FlatCap )
3193 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3197 if ( i < inputPoints.size() - 1 )
3202 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3204 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3205 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3210 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3213 const QgsPoint nextSegmentStartPointLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3214 const QgsPoint nextSegmentEndPointLeft =
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3215 const QgsPoint nextSegmentStartPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3216 const QgsPoint nextSegmentEndPointRight =
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3222 bool isIntersection =
false;
3224 if ( !isIntersection )
3225 thisSegmentPolygonEndLeft = endPointLeft;
3226 isIntersection =
false;
3227 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3228 if ( !isIntersection )
3229 thisSegmentPolygonEndRight = endPointRight;
3231 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3232 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3240 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3241 thisSegmentPolygonEndRight = startLinePolygonRight;
3243 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3244 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3248 thisSegmentPolygonEndLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3249 if ( cap != Qt::PenCapStyle::FlatCap )
3250 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3251 thisSegmentPolygonEndRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3252 if ( cap != Qt::PenCapStyle::FlatCap )
3253 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3255 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3256 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3262 QTransform brushTransform;
3263 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3264 brushTransform.rotate( -segmentAngleDegrees );
3265 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3269 brushTransform.translate( -( lineThickness / 2 ), 0 );
3271 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3273 brush.setTransform( brushTransform );
3274 imagePainter.setBrush( brush );
3277 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3278 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3279 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3280 << prevSegmentPolygonEndRight.
toQPointF()
3281 << prevSegmentPolygonEndLeft.
toQPointF() );
3284 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3285 imagePainter.setBrush( Qt::NoBrush );
3286 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3287 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3288 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3289 << prevSegmentPolygonEndRight.
toQPointF()
3290 << prevSegmentPolygonEndLeft.
toQPointF() );
3291 imagePainter.setPen( Qt::NoPen );
3296 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3297 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3298 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3299 progressThroughImage = fmod( progressThroughImage, patternLength );
3302 segmentStartPoint = segmentEndPoint;
3303 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3304 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3312 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3313 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3330 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique<QgsRasterLineSymbolLayer>();
3332 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3334 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3336 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3340 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3345 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
3346 res->setPath(
properties[QStringLiteral(
"imageFile" )].toString() );
3348 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3350 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3352 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3356 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3361 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3363 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3366 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
3368 res->setOpacity(
properties[QStringLiteral(
"alpha" )].toDouble() );
3371 return res.release();
3378 map[QStringLiteral(
"imageFile" )] =
mPath;
3380 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3387 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3391 map[QStringLiteral(
"alpha" )] = QString::number(
mOpacity );
3398 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3410 return res.release();
3415 const QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
3416 if ( it !=
properties.end() && it.value().type() == QVariant::String )
3432 return QStringLiteral(
"RasterLine" );
3442 bool cached =
false;
3444 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3445 static_cast< int >( std::ceil( scaledHeight ) ) ),
3470 double strokeWidth =
mWidth;
3487 bool cached =
false;
3489 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3490 static_cast< int >( std::ceil( scaledHeight ) ) ),
3495 if ( useSelectedColor )
3500 const QBrush brush( sourceImage );
3570 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique<QgsLineburstSymbolLayer>();
3572 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3574 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3576 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3580 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3585 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3587 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3589 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3593 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3598 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3600 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3603 if (
properties.contains( QStringLiteral(
"color_type" ) ) )
3606 if (
properties.contains( QStringLiteral(
"color" ) ) )
3610 if (
properties.contains( QStringLiteral(
"gradient_color2" ) ) )
3625 return res.release();
3632 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3639 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3645 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
3656 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique< QgsLineburstSymbolLayer >();
3672 return res.release();
3677 return QStringLiteral(
"Lineburst" );
3693 double strokeWidth =
mWidth;
3709 if ( useSelectedColor )
3713 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3724 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3736 gradient.setColorAt( 0.0, color1 );
3737 gradient.setColorAt( 1.0,
color2 );
3739 const QBrush brush( gradient );
3818 if ( props.contains( QStringLiteral(
"line_width" ) ) )
3820 width = props[QStringLiteral(
"line_width" )].toDouble();
3822 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
3824 width = props[QStringLiteral(
"outline_width" )].toDouble();
3826 else if ( props.contains( QStringLiteral(
"width" ) ) )
3828 width = props[QStringLiteral(
"width" )].toDouble();
3833 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
3837 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
3841 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
3846 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3848 if ( props.contains( QStringLiteral(
"offset" ) ) )
3849 l->setOffset( props[QStringLiteral(
"offset" )].toDouble() );
3850 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
3852 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3854 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
3856 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
3859 l->restoreOldDataDefinedProperties( props );
3866 return QStringLiteral(
"FilledLine" );
3900 Qt::PenJoinStyle join = mPenJoinStyle;
3909 Qt::PenCapStyle cap = mPenCapStyle;
3925 const double prevOpacity = mFill->opacity();
3926 mFill->setOpacity( mFill->opacity() * context.
opacity() );
3934 QPainterPathStroker stroker;
3935 stroker.setWidth( scaledWidth );
3936 stroker.setCapStyle( cap );
3937 stroker.setJoinStyle( join );
3943 path.addPolygon( points );
3944 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3945 const QPolygonF polygon = stroke.toFillPolygon();
3946 if ( !polygon.isEmpty() )
3948 mFill->renderPolygon( polygon,
nullptr, context.
feature(), context.
renderContext(), -1, useSelectedColor );
3962 for (
const QPolygonF &part : mline )
3965 path.addPolygon( part );
3966 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3967 const QPolygonF polygon = stroke.toFillPolygon();
3968 if ( !polygon.isEmpty() )
3970 mFill->renderPolygon( polygon,
nullptr, context.
feature(), context.
renderContext(), -1, useSelectedColor );
3977 mFill->setOpacity( prevOpacity );
3984 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3989 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
4004 res->setSubSymbol( mFill->clone() );
4005 return res.release();
4040 attr.unite( mFill->usedAttributes( context ) );
4048 if ( mFill && mFill->hasDataDefinedProperties() )
4057 mFill->setColor(
c );
4062 return mFill ? mFill->color() :
mColor;
4069 || ( mFill && mFill->usesMapUnits() );
4076 mFill->setMapUnitScale( scale );
4083 return mFill->mapUnitScale();
4092 mFill->setOutputUnit( unit );
4099 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) (since QGIS 3....
@ LastVertex
Place symbols on the last vertex in the line.
@ CentralPoint
Place symbols at the mid point of the line.
@ SegmentCenter
Place symbols at the center of every line segment.
@ Vertex
Place symbols on every vertex in the line.
@ Interval
Place symbols at regular intervals.
@ FirstVertex
Place symbols on the first vertex in the line.
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
GradientColorSource
Gradient color sources.
@ ColorRamp
Gradient color ramp.
@ Curve
An intermediate point on a segment defining the curvature of the segment.
@ Segment
The actual start or end point of a segment.
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.
@ RenderingSubSymbol
Set whenever a sub-symbol of a parent symbol is currently being rendered. Can be used during symbol a...
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
Base class for line symbol layer types which draws line sections using a QBrush.
Qt::PenCapStyle mPenCapStyle
Qt::PenJoinStyle mPenJoinStyle
void renderPolylineUsingBrush(const QPolygonF &points, QgsSymbolRenderContext &context, const QBrush &brush, double patternThickness, double patternLength)
Renders a polyline of points using the specified brush.
static bool isGeneralizableByDeviceBoundingBox(const QgsRectangle &envelope, float mapToPixelTol=1.0f)
Returns whether the device-envelope can be replaced by its BBOX when is applied the specified toleran...
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
Abstract base class for color ramps.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Curve polygon geometry type.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Exports QGIS layers to the DXF format.
static double mapUnitScaleFactor(double scale, Qgis::RenderUnit symbolUnits, Qgis::DistanceUnit mapUnits, double mapUnitsPerPixel=1.0)
Returns scale factor for conversion to map units.
Qgis::DistanceUnit mapUnits() const
Retrieve map units.
double symbologyScale() const
Returns the reference scale for output.
void clipValueToMapUnitScale(double &value, const QgsMapUnitScale &scale, double pixelToMMFactor) const
Clips value to scale minimum/maximum.
RAII class to pop scope from an expression context on destruction.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
static const QString EXPR_GEOMETRY_POINT_COUNT
Inbuilt variable name for point count variable.
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
static const QString EXPR_GEOMETRY_RING_NUM
Inbuilt variable name for geometry ring number variable.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isCanceled() const
Tells whether the operation has been canceled already.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
A line symbol layer type which fills a stroked line with a QgsFillSymbol.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString layerType() const override
Returns a string that represents this layer type.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFilledLineSymbolLayer, using the settings serialized in the properties map (correspo...
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
~QgsFilledLineSymbolLayer() override
QgsFilledLineSymbolLayer(double width=DEFAULT_SIMPLELINE_WIDTH, QgsFillSymbol *fillSymbol=nullptr)
Constructor for QgsFilledLineSymbolLayer.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setColor(const QColor &c) override
Sets the "representative" color for the symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
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.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
void addStopsToGradient(QGradient *gradient, double opacity=1) const
Copy color ramp stops to a QGradient.
Line symbol layer type which draws repeating line sections along a line feature.
double hashAngle() const
Returns the angle to use when drawing the hashed lines sections, in degrees clockwise.
QgsHashedLineSymbolLayer(bool rotateSymbol=true, double interval=3)
Constructor for QgsHashedLineSymbolLayer.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setWidth(double width) override
Sets the width of the line symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
double width() const override
Returns the estimated width for the line symbol layer.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsHashedLineSymbolLayer, using the settings serialized in the properties map (correspo...
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsHashedLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
~QgsHashedLineSymbolLayer() override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QColor color() const override
Returns the "representative" color of the symbol layer.
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString layerType() const override
Returns a string that represents this layer type.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setHashAngle(double angle)
Sets the angle to use when drawing the hashed lines sections, in degrees clockwise.
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
static void overlayColor(QImage &image, const QColor &color)
Overlays a color onto an image.
Qgis::RenderUnit mOffsetUnit
RenderRingFilter
Options for filtering rings when the line symbol layer is being used to render a polygon's rings.
@ ExteriorRingOnly
Render the exterior ring only.
@ InteriorRingsOnly
Render the interior rings only.
@ AllRings
Render both exterior and interior rings.
QgsMapUnitScale mWidthMapUnitScale
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void setWidthMapUnitScale(const QgsMapUnitScale &scale)
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit mWidthUnit
void setOffset(double offset)
Sets the line's offset.
RenderRingFilter mRingFilter
void setOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the line's offset.
void setWidthUnit(Qgis::RenderUnit unit)
Sets the units for the line's width.
virtual double width() const
Returns the estimated width for the line symbol layer.
QgsMapUnitScale mOffsetMapUnitScale
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the line's offset.
QgsMapUnitScale mapUnitScale() const override
void setRingFilter(QgsLineSymbolLayer::RenderRingFilter filter)
Sets the line symbol layer's ring filter, which controls which rings are rendered when the line symbo...
void setMapUnitScale(const QgsMapUnitScale &scale) override
double offset() const
Returns the line's offset.
Qgis::RenderUnit offsetUnit() const
Returns the units for the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
Line symbol layer type which draws a gradient pattern perpendicularly along a line.
std::unique_ptr< QgsColorRamp > mGradientRamp
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp used for the gradient line.
QColor color2() const
Returns the color for endpoint of gradient, only used if the gradient color type is set to SimpleTwoC...
Qgis::GradientColorSource mGradientColorType
QString layerType() const override
Returns a string that represents this layer type.
~QgsLineburstSymbolLayer() override
QgsLineburstSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsMapUnitScale mapUnitScale() const override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsLineburstSymbolLayer, using the settings serialized in the properties map (correspon...
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QgsLineburstSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, const QColor &color2=Qt::white)
Constructor for QgsLineburstSymbolLayer, with the specified start and end gradient colors.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsColorRamp * colorRamp()
Returns the color ramp used for the gradient line.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
void transformInPlace(double &x, double &y) const
Transforms device coordinates to map coordinates.
Struct for storing maximum and minimum scales for measurements in map units.
Line symbol layer type which draws repeating marker symbols along a line feature.
Q_DECL_DEPRECATED bool rotateMarker() const
Shall the marker be rotated.
std::unique_ptr< QgsMarkerSymbol > mMarker
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsMarkerLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
double width() const override
Returns the estimated width for the line symbol layer.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsMarkerLineSymbolLayer, using the settings serialized in the properties map (correspo...
QgsMarkerLineSymbolLayer(bool rotateMarker=DEFAULT_MARKERLINE_ROTATE, double interval=DEFAULT_MARKERLINE_INTERVAL)
Constructor for QgsMarkerLineSymbolLayer.
void setWidth(double width) override
Sets the width of the line symbol layer.
QColor color() const override
Returns the "representative" color of the symbol layer.
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
~QgsMarkerLineSymbolLayer() override
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QString layerType() const override
Returns a string that represents this layer type.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsMarkerLineSymbolLayer from an SLD XML DOM element.
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
Abstract base class for marker symbol layers.
A marker symbol type, for rendering Point and MultiPoint geometries.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Resolves relative paths into absolute paths and vice versa.
A class to represent a 2D point.
QgsPointXY project(double distance, double bearing) const
Returns a new point which corresponds to this point projected by a specified distance in a specified ...
Point geometry type, with support for z-dimension and m-values.
QPointF toQPointF() const
Returns the point as a QPointF.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const final
Returns the calculated value of the property with the specified key from within the collection.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
A store for object properties.
Line symbol layer type which draws line sections using a raster image file.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QgsRasterLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
double opacity() const
Returns the line opacity.
QString path() const
Returns the raster image path.
void setPath(const QString &path)
Set the raster image path.
QString layerType() const override
Returns a string that represents this layer type.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
QgsRasterLineSymbolLayer(const QString &path=QString())
Constructor for QgsRasterLineSymbolLayer, with the specified raster image path.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsRasterLineSymbolLayer, using the settings serialized in the properties map (correspo...
QColor color() const override
Returns the "representative" color of the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsMapUnitScale mapUnitScale() const override
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
virtual ~QgsRasterLineSymbolLayer()
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
const QgsVectorSimplifyMethod & vectorSimplifyMethod() const
Returns the simplification settings to use when rendering vector layers.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QColor selectionColor() const
Returns the color to use when rendering selected features.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
const QgsAbstractGeometry * geometry() const
Returns pointer to the unsegmentized geometry.
Scoped object for saving and restoring a QPainter object's state.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void setDrawInsidePolygon(bool drawInsidePolygon)
Sets whether the line should only be drawn inside polygons, and any portion of the line which falls o...
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QgsMapUnitScale mapUnitScale() const override
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QVector< qreal > customDashVector() const
Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the outline of polygon, using the given render context.
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
void setCustomDashPatternMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for lengths used in the custom dash pattern.
void setTrimDistanceEndMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the end of the line.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void setTrimDistanceEnd(double distance)
Sets the trim distance for the end of the line, which dictates a length from the end of the line at w...
double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets offset.
QgsSimpleLineSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, double width=DEFAULT_SIMPLELINE_WIDTH, Qt::PenStyle penStyle=DEFAULT_SIMPLELINE_PENSTYLE)
Constructor for QgsSimpleLineSymbolLayer.
~QgsSimpleLineSymbolLayer() override
void setUseCustomDashPattern(bool b)
Sets whether the line uses a custom dash pattern.
void setTweakDashPatternOnCorners(bool enabled)
Sets whether dash patterns tweaks should be applied on sharp corners, to ensure that a double-length ...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
void setCustomDashVector(const QVector< qreal > &vector)
Sets the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ren...
void setDashPatternOffset(double offset)
Sets the dash pattern offset, which dictates how far along the dash pattern the pattern should start ...
QColor dxfColor(QgsSymbolRenderContext &context) const override
Gets color.
QString layerType() const override
Returns a string that represents this layer type.
void setDashPatternOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the dash pattern offset.
QgsSimpleLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
void setAlignDashPattern(bool enabled)
Sets whether dash patterns should be aligned to the start and end of lines, by applying subtle tweaks...
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleLineSymbolLayer from an SLD XML DOM element.
double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets line width.
void setTrimDistanceStartMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the start of the line.
QVector< qreal > dxfCustomDashPattern(Qgis::RenderUnit &unit) const override
Gets dash pattern.
Qt::PenCapStyle penCapStyle() const
Returns the pen cap style used to render the line (e.g.
void setTrimDistanceEndUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the end of the line.
void setDashPatternOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the dash pattern offset.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setTrimDistanceStart(double distance)
Sets the trim distance for the start of the line, which dictates a length from the start of the line ...
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setTrimDistanceStartUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the start of the line.
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
void setCustomDashPatternUnit(Qgis::RenderUnit unit)
Sets the unit for lengths used in the custom dash pattern.
static QString encodePenStyle(Qt::PenStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static QString encodeColor(const QColor &color)
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static Qt::PenStyle decodePenStyle(const QString &str)
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static QString encodeRealVector(const QVector< qreal > &v)
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
bool shouldRenderUsingSelectionColor(const QgsSymbolRenderContext &context) const
Returns true if the symbol layer should be rendered using the selection color from the render context...
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
Property
Data definable properties.
@ SecondaryColor
Secondary color (eg for gradient fills)
@ File
Filename, eg for svg files.
@ DashPatternOffset
Dash pattern offset,.
@ OffsetAlongLine
Offset along line.
@ CustomDash
Custom dash pattern.
@ StrokeStyle
Stroke style (eg solid, dashed)
@ StrokeColor
Stroke color.
@ TrimStart
Trim distance from start of line (since QGIS 3.20)
@ CapStyle
Line cap style.
@ Placement
Line marker placement.
@ LineAngle
Line angle, or angle of hash lines for hash line symbols.
@ JoinStyle
Line join style.
@ AverageAngleLength
Length to average symbol angles over.
@ Interval
Line marker interval.
@ StrokeWidth
Stroke width.
@ LineDistance
Distance between lines, or length of lines for hash line symbols.
@ TrimEnd
Trim distance from end of line (since QGIS 3.20)
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
const QgsFeature * feature() const
Returns the current feature being rendered.
Qgis::GeometryType originalGeometryType() const
Returns the geometry type for the original feature geometry being rendered.
QgsFields fields() const
Fields of the layer.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
qreal opacity() const
Returns the opacity for the symbol.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for all rendered symbols.
qreal opacity() const
Returns the opacity for the symbol.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
Base class for templated line symbols, e.g.
bool rotateSymbols() const
Returns true if the repeating symbols be rotated to match their line segment orientation.
Qgis::RenderUnit outputUnit() const FINAL
Returns the units to use for sizes and widths within the symbol layer.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
static void setCommonProperties(QgsTemplatedLineSymbolLayerBase *destLayer, const QVariantMap &properties)
Sets all common symbol properties in the destLayer, using the settings serialized in the properties m...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
QgsMapUnitScale mapUnitScale() const FINAL
void setMapUnitScale(const QgsMapUnitScale &scale) FINAL
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setIntervalUnit(Qgis::RenderUnit unit)
Sets the units for the interval between symbols.
void setAverageAngleUnit(Qgis::RenderUnit unit)
Sets the unit for the length over which the line's direction is averaged when calculating individual ...
double interval() const
Returns the interval between individual symbols.
void setOffsetAlongLineUnit(Qgis::RenderUnit unit)
Sets the unit used for calculating the offset along line for symbols.
void setAverageAngleMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the length over which the line's direction is averaged when calculating i...
const QgsMapUnitScale & intervalMapUnitScale() const
Returns the map unit scale for the interval between symbols.
double offsetAlongLine() const
Returns the offset along the line for the symbol placement.
~QgsTemplatedLineSymbolLayerBase() override
void copyTemplateSymbolProperties(QgsTemplatedLineSymbolLayerBase *destLayer) const
Copies all common properties of this layer to another templated symbol layer.
Qgis::MarkerLinePlacements placements() const
Returns the placement of the symbols.
void setOffsetAlongLine(double offsetAlongLine)
Sets the the offset along the line for the symbol placement.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) FINAL
Renders the line symbol layer along the outline of polygon, using the given render context.
Qgis::RenderUnit offsetAlongLineUnit() const
Returns the unit used for calculating the offset along line for symbols.
QgsTemplatedLineSymbolLayerBase(bool rotateSymbol=true, double interval=3)
Constructor for QgsTemplatedLineSymbolLayerBase.
virtual void setSymbolLineAngle(double angle)=0
Sets the line angle modification for the symbol's angle.
void setInterval(double interval)
Sets the interval between individual symbols.
Qgis::RenderUnit intervalUnit() const
Returns the units for the interval between symbols.
Q_DECL_DEPRECATED Qgis::MarkerLinePlacement placement() const
Returns the placement of the symbols.
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
void setPlaceOnEveryPart(bool respect)
Sets whether the placement applies for every part of multi-part feature geometries.
void setPlacements(Qgis::MarkerLinePlacements placements)
Sets the placement of the symbols.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit averageAngleUnit() const
Returns the unit for the length over which the line's direction is averaged when calculating individu...
Q_DECL_DEPRECATED void setPlacement(Qgis::MarkerLinePlacement placement)
Sets the placement of the symbols.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
const QgsMapUnitScale & offsetAlongLineMapUnitScale() const
Returns the map unit scale used for calculating the offset in map units along line for symbols.
virtual void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false)=0
Renders the templated symbol at the specified point, using the given render context.
void setIntervalMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the interval between symbols.
void setOffsetAlongLineMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale used for calculating the offset in map units along line for symbols.
void setAverageAngleLength(double length)
Sets the length of line over which the line's direction is averaged when calculating individual symbo...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QMap< QString, QString > QgsStringMap
#define DEFAULT_MARKERLINE_INTERVAL
#define DEFAULT_SIMPLELINE_WIDTH
#define DEFAULT_MARKERLINE_ROTATE
#define DEFAULT_SIMPLELINE_PENSTYLE
#define DEFAULT_SIMPLELINE_COLOR
#define QgsDebugMsgLevel(str, level)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
Single variable definition for use within a QgsExpressionContextScope.
Utility class for identifying a unique vertex within a geometry.
Qgis::VertexType type
Vertex type.