39 #include <QDomDocument>
40 #include <QDomElement>
45 : mPenStyle( penStyle )
49 mCustomDashVector << 5 << 2;
59 mCustomDashPatternUnit = unit;
83 mCustomDashPatternMapUnitScale = scale;
103 if ( props.contains( QStringLiteral(
"line_color" ) ) )
107 else if ( props.contains( QStringLiteral(
"outline_color" ) ) )
111 else if ( props.contains( QStringLiteral(
"color" ) ) )
116 if ( props.contains( QStringLiteral(
"line_width" ) ) )
118 width = props[QStringLiteral(
"line_width" )].toDouble();
120 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
122 width = props[QStringLiteral(
"outline_width" )].toDouble();
124 else if ( props.contains( QStringLiteral(
"width" ) ) )
127 width = props[QStringLiteral(
"width" )].toDouble();
129 if ( props.contains( QStringLiteral(
"line_style" ) ) )
133 else if ( props.contains( QStringLiteral(
"outline_style" ) ) )
137 else if ( props.contains( QStringLiteral(
"penstyle" ) ) )
143 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
147 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
151 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
156 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
158 if ( props.contains( QStringLiteral(
"offset" ) ) )
159 l->
setOffset( props[QStringLiteral(
"offset" )].toDouble() );
160 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
162 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
164 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
166 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
169 if ( props.contains( QStringLiteral(
"use_custom_dash" ) ) )
173 if ( props.contains( QStringLiteral(
"customdash" ) ) )
177 if ( props.contains( QStringLiteral(
"customdash_unit" ) ) )
181 if ( props.contains( QStringLiteral(
"customdash_map_unit_scale" ) ) )
186 if ( props.contains( QStringLiteral(
"draw_inside_polygon" ) ) )
191 if ( props.contains( QStringLiteral(
"ring_filter" ) ) )
196 if ( props.contains( QStringLiteral(
"dash_pattern_offset" ) ) )
198 if ( props.contains( QStringLiteral(
"dash_pattern_offset_unit" ) ) )
200 if ( props.contains( QStringLiteral(
"dash_pattern_offset_map_unit_scale" ) ) )
203 if ( props.contains( QStringLiteral(
"trim_distance_start" ) ) )
205 if ( props.contains( QStringLiteral(
"trim_distance_start_unit" ) ) )
207 if ( props.contains( QStringLiteral(
"trim_distance_start_map_unit_scale" ) ) )
209 if ( props.contains( QStringLiteral(
"trim_distance_end" ) ) )
211 if ( props.contains( QStringLiteral(
"trim_distance_end_unit" ) ) )
213 if ( props.contains( QStringLiteral(
"trim_distance_end_map_unit_scale" ) ) )
216 if ( props.contains( QStringLiteral(
"align_dash_pattern" ) ) )
219 if ( props.contains( QStringLiteral(
"tweak_dash_pattern_on_corners" ) ) )
229 return QStringLiteral(
"SimpleLine" );
236 mPen.setColor( penColor );
238 mPen.setWidthF( scaledWidth );
242 const double dashWidthDiv = std::max( 1.0, scaledWidth );
243 if ( mUseCustomDashPattern )
245 mPen.setStyle( Qt::CustomDashLine );
249 QVector<qreal> scaledVector;
250 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
251 for ( ; it != mCustomDashVector.constEnd(); ++it )
256 mPen.setDashPattern( scaledVector );
260 mPen.setStyle( mPenStyle );
263 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
268 mPen.setJoinStyle( mPenJoinStyle );
269 mPen.setCapStyle( mPenCapStyle );
274 selColor.setAlphaF( context.
opacity() );
275 mSelPen.setColor( selColor );
292 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
299 if ( mDrawInsidePolygon )
307 if ( mDrawInsidePolygon )
310 QPainterPath clipPath;
311 clipPath.addPolygon( points );
316 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
318 QPolygonF ring = *it;
319 clipPath.addPolygon( ring );
324 p->setClipPath( clipPath, Qt::IntersectClip );
347 for (
const QPolygonF &ring : std::as_const( *rings ) )
363 if ( mDrawInsidePolygon )
379 QPolygonF points = pts;
381 double startTrim = mTrimDistanceStart;
387 double endTrim = mTrimDistanceEnd;
394 double totalLength = -1;
398 startTrim = startTrim * 0.01 * totalLength;
406 if ( totalLength < 0 )
408 endTrim = endTrim * 0.01 * totalLength;
421 mPen.setColor( penColor );
424 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
426 const QPen pen = context.
selected() ? mSelPen : mPen;
428 if ( !pen.dashPattern().isEmpty() )
431 const QVector<double> pattern = pen.dashPattern();
432 bool foundNonNull =
false;
433 for (
int i = 0; i < pattern.size(); ++i )
445 p->setBrush( Qt::NoBrush );
448 std::unique_ptr< QgsScopedQPainterState > painterState;
449 if ( points.size() <= 2 &&
452 ( p->renderHints() & QPainter::Antialiasing ) )
454 painterState = std::make_unique< QgsScopedQPainterState >( p );
455 p->setRenderHint( QPainter::Antialiasing,
false );
458 const bool applyPatternTweaks = mAlignDashPattern
459 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
460 && pen.dashOffset() == 0;
464 if ( applyPatternTweaks )
466 drawPathWithDashPatternTweaks( p, points, pen );
472 path.addPolygon( points );
487 for (
const QPolygonF &part : mline )
489 if ( applyPatternTweaks )
491 drawPathWithDashPatternTweaks( p, part, pen );
497 path.addPolygon( part );
508 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
514 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
517 map[QStringLiteral(
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
521 map[QStringLiteral(
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
524 map[QStringLiteral(
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
527 map[QStringLiteral(
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
530 map[QStringLiteral(
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
531 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
532 map[QStringLiteral(
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
533 map[QStringLiteral(
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
572 if ( mPenStyle == Qt::NoPen )
575 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
576 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
577 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
578 element.appendChild( symbolizerElem );
584 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
585 symbolizerElem.appendChild( strokeElem );
587 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
596 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
599 symbolizerElem.appendChild( perpOffsetElem );
605 if ( mUseCustomDashPattern )
608 mPen.color(), mPenJoinStyle,
609 mPenCapStyle,
mOffset, &mCustomDashVector );
622 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
623 if ( strokeElem.isNull() )
640 QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
641 if ( !perpOffsetElem.isNull() )
644 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
649 QString uom = element.attribute( QStringLiteral(
"uom" ) );
663 void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
669 bool hasStrokeWidthExpression =
false;
676 pen.setWidthF( scaledWidth );
677 selPen.setWidthF( scaledWidth );
678 hasStrokeWidthExpression =
true;
687 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
688 pen.setColor( penColor );
702 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
706 QVector<qreal> dashVector;
708 if ( !exprVal.isNull() )
710 QStringList dashList = exprVal.toString().split(
';' );
711 QStringList::const_iterator dashIt = dashList.constBegin();
712 for ( ; dashIt != dashList.constEnd(); ++dashIt )
716 pen.setDashPattern( dashVector );
723 QVector<qreal> scaledVector;
724 for (
double v : std::as_const( mCustomDashVector ) )
729 mPen.setDashPattern( scaledVector );
733 double patternOffset = mDashPatternOffset;
746 if ( !exprVal.isNull() )
755 if ( !exprVal.isNull() )
764 if ( !exprVal.isNull() )
769 void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
771 if ( pen.dashPattern().empty() || points.size() < 2 )
774 QVector< qreal > sourcePattern = pen.dashPattern();
775 const double dashWidthDiv = std::max( 1.0001, pen.widthF() );
777 for (
int i = 0; i < sourcePattern.size(); ++ i )
778 sourcePattern[i] *= pen.widthF();
780 if ( pen.widthF() <= 1.0 )
781 pen.setWidthF( 1.0001 );
783 QVector< qreal > buffer;
784 QPolygonF bufferedPoints;
785 QPolygonF previousSegmentBuffer;
790 auto ptIt = points.constBegin();
791 double totalBufferLength = 0;
792 int patternIndex = 0;
793 double currentRemainingDashLength = 0;
794 double currentRemainingGapLength = 0;
796 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
798 QVector< qreal > result;
799 result.reserve( buffer.size() );
800 for (
auto it = buffer.begin(); it != buffer.end(); )
804 while ( dash == 0 && !result.empty() )
806 result.last() += gap;
808 if ( it == buffer.end() )
813 while ( gap == 0 && it != buffer.end() )
818 result << dash << gap;
823 double currentBufferLineLength = 0;
824 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
825 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
827 if ( buffer.empty() || bufferedPoints.size() < 2 )
832 if ( currentRemainingDashLength )
835 buffer << currentRemainingDashLength << 0.0;
836 totalBufferLength += currentRemainingDashLength;
838 QVector< qreal > compressed = compressPattern( buffer );
839 if ( !currentRemainingDashLength )
842 totalBufferLength -= compressed.last();
843 compressed.last() = 0;
847 const double scaleFactor = currentBufferLineLength / totalBufferLength;
849 bool shouldFlushPreviousSegmentBuffer =
false;
851 if ( !previousSegmentBuffer.empty() )
855 if ( !firstDashSubstring.empty() )
861 compressed = compressed.mid( 2 );
862 shouldFlushPreviousSegmentBuffer = !compressed.empty();
865 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
867 QPen adjustedPen = pen;
868 adjustedPen.setStyle( Qt::SolidLine );
869 painter->setPen( adjustedPen );
871 path.addPolygon( previousSegmentBuffer );
872 painter->drawPath( path );
873 previousSegmentBuffer.clear();
876 double finalDash = 0;
883 if ( !compressed.empty() )
885 finalDash = compressed.at( compressed.size() - 2 );
886 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
888 const QPolygonF thisPoints = bufferedPoints;
894 previousSegmentBuffer << bufferedPoints;
898 currentBufferLineLength = 0;
899 currentRemainingDashLength = 0;
900 currentRemainingGapLength = 0;
901 totalBufferLength = 0;
904 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
906 QPen adjustedPen = pen;
907 if ( !compressed.empty() )
910 compressed = compressed.mid( 0, 32 );
911 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
912 adjustedPen.setDashPattern( compressed );
916 adjustedPen.setStyle( Qt::SolidLine );
919 painter->setPen( adjustedPen );
921 path.addPolygon( bufferedPoints );
922 painter->drawPath( path );
925 bufferedPoints.clear();
931 bufferedPoints << p2;
932 for ( ; ptIt != points.constEnd(); ++ptIt )
940 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
941 currentBufferLineLength += remainingSegmentDistance;
945 if ( currentRemainingDashLength > 0 )
948 if ( remainingSegmentDistance >= currentRemainingDashLength )
951 buffer << currentRemainingDashLength << 0.0;
952 totalBufferLength += currentRemainingDashLength;
953 remainingSegmentDistance -= currentRemainingDashLength;
955 currentRemainingDashLength = 0.0;
956 currentRemainingGapLength = sourcePattern.at( patternIndex );
961 buffer << remainingSegmentDistance << 0.0;
962 totalBufferLength += remainingSegmentDistance;
963 currentRemainingDashLength -= remainingSegmentDistance;
967 if ( currentRemainingGapLength > 0 )
970 if ( remainingSegmentDistance >= currentRemainingGapLength )
973 buffer << 0.0 << currentRemainingGapLength;
974 totalBufferLength += currentRemainingGapLength;
975 remainingSegmentDistance -= currentRemainingGapLength;
976 currentRemainingGapLength = 0.0;
982 buffer << 0.0 << remainingSegmentDistance;
983 totalBufferLength += remainingSegmentDistance;
984 currentRemainingGapLength -= remainingSegmentDistance;
989 if ( patternIndex >= sourcePattern.size() )
992 const double nextPatternDashLength = sourcePattern.at( patternIndex );
993 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
994 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
996 buffer << nextPatternDashLength << nextPatternGapLength;
997 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
998 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1001 else if ( nextPatternDashLength <= remainingSegmentDistance )
1004 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1005 totalBufferLength += remainingSegmentDistance;
1006 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1007 currentRemainingDashLength = 0;
1014 buffer << remainingSegmentDistance << 0.0;
1015 totalBufferLength += remainingSegmentDistance;
1016 currentRemainingGapLength = 0;
1017 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1022 bufferedPoints << p1;
1023 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1025 QPointF nextPoint = *( ptIt + 1 );
1031 flushBuffer( &nextPoint );
1032 bufferedPoints << p1;
1035 if ( patternIndex % 2 == 1 )
1039 currentRemainingDashLength = sourcePattern.at( patternIndex );
1046 flushBuffer(
nullptr );
1047 if ( !previousSegmentBuffer.empty() )
1049 QPen adjustedPen = pen;
1050 adjustedPen.setStyle( Qt::SolidLine );
1051 painter->setPen( adjustedPen );
1053 path.addPolygon( previousSegmentBuffer );
1054 painter->drawPath( path );
1055 previousSegmentBuffer.clear();
1061 if ( mDrawInsidePolygon )
1075 unit = mCustomDashPatternUnit;
1076 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1113 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1118 return mAlignDashPattern;
1128 return mPatternCartographicTweakOnSharpCorners;
1133 mPatternCartographicTweakOnSharpCorners =
enabled;
1161 MyLine( QPointF p1, QPointF p2 )
1162 : mVertical( false )
1163 , mIncreasing( false )
1175 mIncreasing = ( p2.y() > p1.y() );
1180 mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
1181 mIncreasing = ( p2.x() > p1.x() );
1185 double x = ( p2.x() - p1.x() );
1186 double y = ( p2.y() - p1.y() );
1187 mLength = std::sqrt( x * x + y * y );
1193 double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
1201 QPointF diffForInterval(
double interval )
1204 return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
1206 double alpha = std::atan( mT );
1207 double dx = std::cos( alpha ) * interval;
1208 double dy = std::sin( alpha ) * interval;
1209 return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
1212 double length() {
return mLength; }
1227 : mRotateSymbols( rotateSymbol )
1228 , mInterval( interval )
1266 if ( mRenderingFeature )
1270 mFeatureSymbolOpacity = context.
opacity();
1271 mCurrentFeatureIsSelected = context.
selected();
1287 if ( !exprVal.isNull() )
1289 QString placementString = exprVal.toString();
1290 if ( placementString.compare( QLatin1String(
"interval" ), Qt::CaseInsensitive ) == 0 )
1294 else if ( placementString.compare( QLatin1String(
"vertex" ), Qt::CaseInsensitive ) == 0 )
1298 else if ( placementString.compare( QLatin1String(
"innervertices" ), Qt::CaseInsensitive ) == 0 )
1302 else if ( placementString.compare( QLatin1String(
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
1306 else if ( placementString.compare( QLatin1String(
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
1310 else if ( placementString.compare( QLatin1String(
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
1314 else if ( placementString.compare( QLatin1String(
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
1318 else if ( placementString.compare( QLatin1String(
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
1331 double averageOver = mAverageAngleLength;
1342 renderPolylineInterval( points, context, averageOver );
1344 renderPolylineCentral( points, context, averageOver );
1348 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1351 mHasRenderedFirstPart = mRenderingFeature;
1367 for (
int part = 0; part < mline.count(); ++part )
1369 const QPolygonF &points2 = mline[ part ];
1372 renderPolylineInterval( points2, context, averageOver );
1374 renderPolylineCentral( points2, context, averageOver );
1382 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1385 mHasRenderedFirstPart = mRenderingFeature;
1405 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1435 for (
int i = 0; i < rings->size(); ++i )
1487 map[QStringLiteral(
"rotate" )] = (
rotateSymbols() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1488 map[QStringLiteral(
"interval" )] = QString::number(
interval() );
1489 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
1490 map[QStringLiteral(
"offset_along_line" )] = QString::number(
offsetAlongLine() );
1497 map[QStringLiteral(
"average_angle_length" )] = QString::number( mAverageAngleLength );
1503 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
1504 map[QStringLiteral(
"place_on_every_part" )] = mPlaceOnEveryPart;
1510 return mPlaceOnEveryPart
1518 mRenderingFeature =
true;
1519 mHasRenderedFirstPart =
false;
1524 mRenderingFeature =
false;
1532 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1533 mFeatureSymbolOpacity = 1;
1560 if (
properties.contains( QStringLiteral(
"offset" ) ) )
1564 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
1568 if (
properties.contains( QStringLiteral(
"interval_unit" ) ) )
1572 if (
properties.contains( QStringLiteral(
"offset_along_line" ) ) )
1576 if (
properties.contains( QStringLiteral(
"offset_along_line_unit" ) ) )
1580 if (
properties.contains( ( QStringLiteral(
"offset_along_line_map_unit_scale" ) ) ) )
1585 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1589 if (
properties.contains( QStringLiteral(
"interval_map_unit_scale" ) ) )
1594 if (
properties.contains( QStringLiteral(
"average_angle_length" ) ) )
1598 if (
properties.contains( QStringLiteral(
"average_angle_unit" ) ) )
1602 if (
properties.contains( ( QStringLiteral(
"average_angle_map_unit_scale" ) ) ) )
1607 if (
properties.contains( QStringLiteral(
"placement" ) ) )
1609 if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"vertex" ) )
1611 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"lastvertex" ) )
1613 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"firstvertex" ) )
1615 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"centralpoint" ) )
1617 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"curvepoint" ) )
1619 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"segmentcenter" ) )
1624 else if (
properties.contains( QStringLiteral(
"placements" ) ) )
1630 if (
properties.contains( QStringLiteral(
"ring_filter" ) ) )
1640 void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver )
1642 if ( points.isEmpty() )
1645 double lengthLeft = 0;
1677 if ( painterUnitInterval < 0 )
1680 double painterUnitOffsetAlongLine = 0;
1683 double totalLength = -1;
1704 if ( points.isClosed() )
1706 if ( painterUnitOffsetAlongLine > 0 )
1708 if ( totalLength < 0 )
1710 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1712 else if ( painterUnitOffsetAlongLine < 0 )
1714 if ( totalLength < 0 )
1716 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1728 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1730 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1732 QVector< QPointF > angleStartPoints;
1733 QVector< QPointF > symbolPoints;
1734 QVector< QPointF > angleEndPoints;
1742 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
1744 if ( symbolPoints.empty() )
1750 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1753 symbolPoints.pop_back();
1756 angleEndPoints.reserve( symbolPoints.size() );
1757 angleStartPoints.reserve( symbolPoints.size() );
1758 if ( averageOver <= painterUnitOffsetAlongLine )
1760 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
1764 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1766 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
1769 for (
int i = 0; i < symbolPoints.size(); ++ i )
1774 const QPointF pt = symbolPoints[i];
1775 const QPointF startPt = angleStartPoints[i];
1776 const QPointF endPt = angleEndPoints[i];
1778 MyLine l( startPt, endPt );
1793 QPointF lastPt = points[0];
1794 for (
int i = 1; i < points.count(); ++i )
1799 const QPointF &pt = points[i];
1805 MyLine l( lastPt, pt );
1806 QPointF diff = l.diffForInterval( painterUnitInterval );
1810 double c = 1 - lengthLeft / painterUnitInterval;
1812 lengthLeft += l.length();
1821 while ( lengthLeft > painterUnitInterval )
1825 lengthLeft -= painterUnitInterval;
1837 static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1840 double a1 = MyLine( prevPt, pt ).angle();
1841 double a2 = MyLine( pt, nextPt ).angle();
1842 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1844 return std::atan2( unitY, unitX );
1849 if ( points.isEmpty() )
1854 int i = -1, maxCount = 0;
1855 bool isRing =
false;
1869 double totalLength = -1;
1889 if ( points.isClosed() )
1893 if ( totalLength < 0 )
1899 if ( totalLength < 0 )
1972 i = points.count() - 1;
1974 maxCount = points.count();
1982 maxCount = points.count() - 1;
1990 maxCount = points.count();
1991 if ( points.first() == points.last() )
2008 renderOffsetVertexAlongLine( points, i, distance, context,
placement );
2015 prevPoint = points.at( 0 );
2017 QPointF symbolPoint;
2018 for ( ; i < maxCount; ++i )
2029 QPointF currentPoint = points.at( i );
2030 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2031 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2034 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2035 currentPoint.x() - prevPoint.x() );
2038 prevPoint = currentPoint;
2042 symbolPoint = points.at( i );
2046 double angle = markerAngle( points, isRing, i );
2051 mFinalVertex = symbolPoint;
2057 double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2060 const QPointF &pt = points[vertex];
2062 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2064 int prevIndex = vertex - 1;
2065 int nextIndex = vertex + 1;
2067 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2069 prevIndex = points.count() - 2;
2073 QPointF prevPoint, nextPoint;
2074 while ( prevIndex >= 0 )
2076 prevPoint = points[ prevIndex ];
2077 if ( prevPoint != pt )
2084 while ( nextIndex < points.count() )
2086 nextPoint = points[ nextIndex ];
2087 if ( nextPoint != pt )
2094 if ( prevIndex >= 0 && nextIndex < points.count() )
2096 angle = _averageAngle( prevPoint, pt, nextPoint );
2103 while ( vertex < points.size() - 1 )
2105 const QPointF &nextPt = points[vertex + 1];
2108 angle = MyLine( pt, nextPt ).angle();
2117 while ( vertex >= 1 )
2119 const QPointF &prevPt = points[vertex - 1];
2122 angle = MyLine( prevPt, pt ).angle();
2134 if ( points.isEmpty() )
2143 bool isRing =
false;
2144 if ( points.first() == points.last() )
2146 double angle = markerAngle( points, isRing, vertex );
2149 mFinalVertex = points[vertex];
2155 int pointIncrement = distance > 0 ? 1 : -1;
2156 QPointF previousPoint = points[vertex];
2157 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2158 int endPoint = distance > 0 ? points.count() - 1 : 0;
2159 double distanceLeft = std::fabs( distance );
2161 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2163 const QPointF &pt = points[i];
2165 if ( previousPoint == pt )
2169 MyLine l( previousPoint, pt );
2171 if ( distanceLeft < l.length() )
2174 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2180 mFinalVertex = markerPoint;
2186 distanceLeft -= l.length();
2193 void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
double initialLag,
int numberPointsRequired )
2198 QVector< QPointF > points = p;
2199 const bool closedRing = points.first() == points.last();
2201 double lengthLeft = initialOffset;
2203 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2204 if ( initialLagLeft < 0 && closedRing )
2207 QPointF lastPt = points.constLast();
2208 QVector< QPointF > pseudoPoints;
2209 for (
int i = points.count() - 2; i > 0; --i )
2211 if ( initialLagLeft >= 0 )
2216 const QPointF &pt = points[i];
2221 MyLine l( lastPt, pt );
2222 initialLagLeft += l.length();
2227 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2229 points = pseudoPoints;
2234 while ( initialLagLeft < 0 )
2236 dest << points.constFirst();
2237 initialLagLeft += intervalPainterUnits;
2240 if ( initialLag > 0 )
2242 lengthLeft += intervalPainterUnits - initialLagLeft;
2245 QPointF lastPt = points[0];
2246 for (
int i = 1; i < points.count(); ++i )
2248 const QPointF &pt = points[i];
2252 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2261 MyLine l( lastPt, pt );
2262 QPointF diff = l.diffForInterval( intervalPainterUnits );
2266 double c = 1 - lengthLeft / intervalPainterUnits;
2268 lengthLeft += l.length();
2271 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2275 lengthLeft -= intervalPainterUnits;
2278 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2283 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2287 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2294 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2297 while ( dest.size() < numberPointsRequired )
2298 dest << points.constLast();
2302 void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver )
2304 if ( !points.isEmpty() )
2308 QPolygonF::const_iterator it = points.constBegin();
2310 for ( ++it; it != points.constEnd(); ++it )
2312 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2313 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2319 const double midPoint = length / 2;
2322 double thisSymbolAngle = 0;
2324 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2326 QVector< QPointF > angleStartPoints;
2327 QVector< QPointF > symbolPoints;
2328 QVector< QPointF > angleEndPoints;
2330 collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
2331 collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
2332 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
2334 pt = symbolPoints.at( 1 );
2335 MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2336 thisSymbolAngle = l.angle();
2341 it = points.constBegin();
2343 qreal last_at = 0, next_at = 0;
2346 for ( ++it; it != points.constEnd(); ++it )
2349 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2350 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2351 if ( next_at >= midPoint )
2359 MyLine l( last, next );
2360 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2361 pt = last + ( next - last ) * k;
2362 thisSymbolAngle = l.angle();
2414 if ( props.contains( QStringLiteral(
"interval" ) ) )
2415 interval = props[QStringLiteral(
"interval" )].toDouble();
2416 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2417 rotate = ( props[QStringLiteral(
"rotate" )].toString() == QLatin1String(
"1" ) );
2419 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2426 return QStringLiteral(
"MarkerLine" );
2443 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2446 mMarker->setRenderHints( hints );
2459 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >(
rotateSymbols(),
interval() );
2466 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2468 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
2469 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2470 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2471 element.appendChild( symbolizerElem );
2501 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2502 symbolizerElem.appendChild( strokeElem );
2505 QDomElement graphicStrokeElem = doc.createElement( QStringLiteral(
"se:GraphicStroke" ) );
2506 strokeElem.appendChild( graphicStrokeElem );
2511 markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
2515 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) ) );
2519 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"Missing marker line symbol layer. Skip it." ) ) );
2522 if ( !gap.isEmpty() )
2524 QDomElement gapElem = doc.createElement( QStringLiteral(
"se:Gap" ) );
2526 graphicStrokeElem.appendChild( gapElem );
2531 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
2534 symbolizerElem.appendChild( perpOffsetElem );
2543 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2544 if ( strokeElem.isNull() )
2547 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
2548 if ( graphicStrokeElem.isNull() )
2556 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2558 if ( it.key() == QLatin1String(
"placement" ) )
2560 if ( it.value() == QLatin1String(
"points" ) )
2562 else if ( it.value() == QLatin1String(
"firstPoint" ) )
2564 else if ( it.value() == QLatin1String(
"lastPoint" ) )
2566 else if ( it.value() == QLatin1String(
"centralPoint" ) )
2569 else if ( it.value() == QLatin1String(
"rotateMarker" ) )
2575 std::unique_ptr< QgsMarkerSymbol > marker;
2589 QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"Gap" ) );
2590 if ( !gapElem.isNull() )
2593 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
2599 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
2600 if ( !perpOffsetElem.isNull() )
2603 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2608 QString uom = element.attribute( QStringLiteral(
"uom" ) );
2630 mMarker->setDataDefinedSize( property );
2637 const double prevOpacity =
mMarker->opacity();
2640 mMarker->setOpacity( prevOpacity );
2663 mMarker->renderPoint( point, feature, context, layer, selected );
2675 return mMarker->size( context );
2681 mMarker->setOutputUnit( unit );
2701 attr.unite(
mMarker->usedAttributes( context ) );
2716 return (
mMarker->size( context ) / 2.0 ) +
2738 if ( props.contains( QStringLiteral(
"interval" ) ) )
2739 interval = props[QStringLiteral(
"interval" )].toDouble();
2740 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2741 rotate = ( props[QStringLiteral(
"rotate" )] == QLatin1String(
"1" ) );
2743 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2745 if ( props.contains( QStringLiteral(
"hash_angle" ) ) )
2747 x->setHashAngle( props[QStringLiteral(
"hash_angle" )].toDouble() );
2750 if ( props.contains( QStringLiteral(
"hash_length" ) ) )
2751 x->setHashLength( props[QStringLiteral(
"hash_length" )].toDouble() );
2753 if ( props.contains( QStringLiteral(
"hash_length_unit" ) ) )
2756 if ( props.contains( QStringLiteral(
"hash_length_map_unit_scale" ) ) )
2764 return QStringLiteral(
"HashLine" );
2770 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2773 mHashSymbol->setRenderHints( hints );
2786 map[ QStringLiteral(
"hash_angle" ) ] = QString::number( mHashAngle );
2788 map[QStringLiteral(
"hash_length" )] = QString::number( mHashLength );
2797 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >(
rotateSymbols(),
interval() );
2799 x->setHashAngle( mHashAngle );
2800 x->setHashLength( mHashLength );
2801 x->setHashLengthUnit( mHashLengthUnit );
2802 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2808 mHashSymbol->setColor(
color );
2814 return mHashSymbol ? mHashSymbol->color() :
mColor;
2819 return mHashSymbol.get();
2830 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2831 mColor = mHashSymbol->color();
2837 mHashLength =
width;
2852 return ( mHashSymbol->width( context ) / 2.0 )
2860 mHashSymbol->setOutputUnit( unit );
2870 attr.unite( mHashSymbol->usedAttributes( context ) );
2878 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
2887 mHashSymbol->setDataDefinedWidth( property );
2900 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
2905 mSymbolLineAngle =
angle;
2910 return mSymbolAngle;
2915 mSymbolAngle =
angle;
2920 double lineLength = mHashLength;
2926 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
2940 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
2945 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
2962 const double prevOpacity = mHashSymbol->opacity();
2963 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
2965 mHashSymbol->setOpacity( prevOpacity );
2984 QPolygonF offsetPoints;
2987 renderLine( points, context, patternThickness, patternLength, brush );
2996 renderLine( part, context, patternThickness, patternLength, brush );
3001 void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3002 const double patternLength,
const QBrush &sourceBrush )
3008 QBrush brush = sourceBrush;
3013 QPolygonF inputPoints;
3014 inputPoints.reserve( points.size() );
3016 double minX = std::numeric_limits< double >::max();
3017 double minY = std::numeric_limits< double >::max();
3018 double maxX = std::numeric_limits< double >::lowest();
3019 double maxY = std::numeric_limits< double >::lowest();
3021 for (
const QPointF &pt : std::as_const( points ) )
3028 minX = std::min( minX, pt.x() );
3029 minY = std::min( minY, pt.y() );
3030 maxX = std::max( maxX, pt.x() );
3031 maxY = std::max( maxY, pt.y() );
3034 if ( inputPoints.size() < 2 )
3038 constexpr
int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3040 constexpr
double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3043 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3044 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3046 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3047 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3049 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3050 if ( temporaryImage.isNull() )
3059 temporaryImage.fill( Qt::transparent );
3068 if ( !exprVal.isNull() )
3077 if ( !exprVal.isNull() )
3082 QPainterPathStroker stroker;
3083 stroker.setWidth( lineThickness );
3084 stroker.setCapStyle( cap );
3085 stroker.setJoinStyle( join );
3088 path.addPolygon( inputPoints );
3089 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3092 QPainter imagePainter;
3093 imagePainter.begin( &temporaryImage );
3095 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3097 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3098 imagePainter.setPen( Qt::NoPen );
3100 QPointF segmentStartPoint = inputPoints.at( 0 );
3103 double progressThroughImage = 0;
3105 QgsPoint prevSegmentPolygonEndLeft;
3106 QgsPoint prevSegmentPolygonEndRight;
3112 for (
int i = 1; i < inputPoints.size(); ++i )
3117 const QPointF segmentEndPoint = inputPoints.at( i );
3119 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3122 QgsPoint thisSegmentPolygonEndLeft;
3123 QgsPoint thisSegmentPolygonEndRight;
3125 QgsPoint thisSegmentPolygonEndLeftForPainter;
3126 QgsPoint thisSegmentPolygonEndRightForPainter;
3134 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3136 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3137 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3141 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtils::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3142 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3145 const QgsPoint lastSegmentStartPointLeft =
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3146 const QgsPoint lastSegmentEndPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3147 const QgsPoint lastSegmentStartPointRight =
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3148 const QgsPoint lastSegmentEndPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3154 bool isIntersection =
false;
3156 if ( !isIntersection )
3157 prevSegmentPolygonEndLeft = startPointLeft;
3158 isIntersection =
false;
3159 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3160 if ( !isIntersection )
3161 prevSegmentPolygonEndRight = startPointRight;
3163 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3164 startLinePolygonRight = prevSegmentPolygonEndRight;
3168 prevSegmentPolygonEndLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3169 if ( cap != Qt::PenCapStyle::FlatCap )
3170 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3171 prevSegmentPolygonEndRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3172 if ( cap != Qt::PenCapStyle::FlatCap )
3173 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3177 if ( i < inputPoints.size() - 1 )
3182 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3184 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3185 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3190 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3193 const QgsPoint nextSegmentStartPointLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3194 const QgsPoint nextSegmentEndPointLeft =
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3195 const QgsPoint nextSegmentStartPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3196 const QgsPoint nextSegmentEndPointRight =
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3202 bool isIntersection =
false;
3204 if ( !isIntersection )
3205 thisSegmentPolygonEndLeft = endPointLeft;
3206 isIntersection =
false;
3207 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3208 if ( !isIntersection )
3209 thisSegmentPolygonEndRight = endPointRight;
3211 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3212 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3220 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3221 thisSegmentPolygonEndRight = startLinePolygonRight;
3223 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3224 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3228 thisSegmentPolygonEndLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3229 if ( cap != Qt::PenCapStyle::FlatCap )
3230 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3231 thisSegmentPolygonEndRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3232 if ( cap != Qt::PenCapStyle::FlatCap )
3233 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3235 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3236 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3242 QTransform brushTransform;
3243 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3244 brushTransform.rotate( -segmentAngleDegrees );
3245 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3249 brushTransform.translate( -( lineThickness / 2 ), 0 );
3251 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3253 brush.setTransform( brushTransform );
3254 imagePainter.setBrush( brush );
3257 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3258 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3259 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3260 << prevSegmentPolygonEndRight.
toQPointF()
3261 << prevSegmentPolygonEndLeft.
toQPointF() );
3264 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3265 imagePainter.setBrush( Qt::NoBrush );
3266 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3267 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3268 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3269 << prevSegmentPolygonEndRight.
toQPointF()
3270 << prevSegmentPolygonEndLeft.
toQPointF() );
3271 imagePainter.setPen( Qt::NoPen );
3276 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3277 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3278 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3279 progressThroughImage = fmod( progressThroughImage, patternLength );
3282 segmentStartPoint = segmentEndPoint;
3283 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3284 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3292 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3293 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3310 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique<QgsRasterLineSymbolLayer>();
3312 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3314 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3316 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3320 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3325 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
3326 res->setPath(
properties[QStringLiteral(
"imageFile" )].toString() );
3328 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3330 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3332 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3336 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3341 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3343 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3346 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
3348 res->setOpacity(
properties[QStringLiteral(
"alpha" )].toDouble() );
3351 return res.release();
3358 map[QStringLiteral(
"imageFile" )] =
mPath;
3360 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3367 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3371 map[QStringLiteral(
"alpha" )] = QString::number(
mOpacity );
3378 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3390 return res.release();
3395 const QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
3396 if ( it !=
properties.end() && it.value().type() == QVariant::String )
3412 return QStringLiteral(
"RasterLine" );
3422 bool cached =
false;
3424 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3425 static_cast< int >( std::ceil( scaledHeight ) ) ),
3450 double strokeWidth =
mWidth;
3467 bool cached =
false;
3469 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3470 static_cast< int >( std::ceil( scaledHeight ) ) ),
3479 const QBrush brush( sourceImage );
3549 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique<QgsLineburstSymbolLayer>();
3551 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3553 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3555 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3559 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3564 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3566 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3568 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3572 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3577 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3579 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3582 if (
properties.contains( QStringLiteral(
"color_type" ) ) )
3585 if (
properties.contains( QStringLiteral(
"color" ) ) )
3589 if (
properties.contains( QStringLiteral(
"gradient_color2" ) ) )
3604 return res.release();
3611 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3618 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3624 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
3627 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
3639 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique< QgsLineburstSymbolLayer >();
3655 return res.release();
3660 return QStringLiteral(
"Lineburst" );
3676 double strokeWidth =
mWidth;
3695 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3706 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3718 gradient.setColorAt( 0.0, color1 );
3719 gradient.setColorAt( 1.0,
color2 );
3721 const QBrush brush( gradient );
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.
@ 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 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 * interiorRing(int i) const SIP_HOLDGIL
Retrieves an interior ring from the curve polygon.
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
Exports QGIS layers to the DXF format.
static double mapUnitScaleFactor(double scale, QgsUnitTypes::RenderUnit symbolUnits, QgsUnitTypes::DistanceUnit mapUnits, double mapUnitsPerPixel=1.0)
Returns scale factor for conversion to map units.
QgsUnitTypes::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 SIP_HOLDGIL
Tells whether the operation has been canceled already.
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) SIP_HOLDGIL
Compute the intersection between two segments.
static double lineAngle(double x1, double y1, double x2, double y2) SIP_HOLDGIL
Calculates the direction of line joining two points in radians, clockwise from the north direction.
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.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
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...
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, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
static void adjustHueSaturation(QImage &image, double saturation, const QColor &colorizeColor=QColor(), double colorizeStrength=1.0, QgsFeedback *feedback=nullptr)
Alter the hue or saturation of a QImage.
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(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QgsUnitTypes::RenderUnit mWidthUnit
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units for the line's offset.
void setWidthMapUnitScale(const QgsMapUnitScale &scale)
void setWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the line's width.
void setOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the line's offset.
void setOffset(double offset)
Sets the line's offset.
RenderRingFilter mRingFilter
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsUnitTypes::RenderUnit widthUnit() const
Returns 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.
QgsUnitTypes::RenderUnit mOffsetUnit
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
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
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 startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QColor color() const override
Returns the "representative" color of the symbol layer.
QgsLineburstSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, const QColor &color2=Qt::white)
Constructor for QgsLineburstSymbolLayer, with the specified start and end gradient colors.
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 setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets 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.
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.
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.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
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 SIP_HOLDGIL
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 SIP_HOLDGIL
Returns the point as a QPointF.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const SIP_HOLDGIL
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 override
Returns the calculated value of the property with the specified key from within the collection.
bool isActive(int key) const override
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.
QgsUnitTypes::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.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
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
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.
const QgsAbstractGeometry * geometry() const
Returns pointer to the unsegmentized geometry.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
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)
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 QgsVectorSimplifyMethod & vectorSimplifyMethod() const
Returns the simplification settings to use when rendering vector layers.
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
QVector< qreal > dxfCustomDashPattern(QgsUnitTypes::RenderUnit &unit) const override
Gets dash pattern.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
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.
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void setDashPatternOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the dash pattern offset.
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
void setCustomDashPatternMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for lengths used in the custom dash pattern.
void setTrimDistanceEndMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the end of the line.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QVector< qreal > customDashVector() const
Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ...
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...
void setCustomDashPatternUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for lengths used in the custom dash pattern.
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.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
void setAlignDashPattern(bool enabled)
Sets whether dash patterns should be aligned to the start and end of lines, by applying subtle tweaks...
void setTrimDistanceStartUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the trim distance for the start of the line.
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.
void setTrimDistanceEndUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the trim distance for the end of the line.
Qt::PenCapStyle penCapStyle() const
Returns the pen cap style used to render the line (e.g.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets 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.
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.
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
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 QColor decodeColor(const QString &str)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static double rescaleUom(double size, QgsUnitTypes::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
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 double sizeInPixelsFromSldUom(const QString &uom, double size)
Returns the size scaled in pixels according to the uom attribute.
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 void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
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)
Property
Data definable properties.
@ PropertyStrokeStyle
Stroke style (eg solid, dashed)
@ PropertyPlacement
Line marker placement.
@ PropertyFile
Filename, eg for svg files.
@ PropertyCapStyle
Line cap style.
@ PropertyLineDistance
Distance between lines, or length of lines for hash line symbols.
@ PropertyOffsetAlongLine
Offset along line.
@ PropertyCustomDash
Custom dash pattern.
@ PropertyJoinStyle
Line join style.
@ PropertyTrimEnd
Trim distance from end of line (since QGIS 3.20)
@ PropertyOpacity
Opacity.
@ PropertySecondaryColor
Secondary color (eg for gradient fills)
@ PropertyLineAngle
Line angle, or angle of hash lines for hash line symbols.
@ PropertyTrimStart
Trim distance from start of line (since QGIS 3.20)
@ PropertyOffset
Symbol offset.
@ PropertyStrokeWidth
Stroke width.
@ PropertyDashPatternOffset
Dash pattern offset,.
@ PropertyAverageAngleLength
Length to average symbol angles over.
@ PropertyInterval
Line marker interval.
@ PropertyStrokeColor
Stroke color.
@ PropertyWidth
Symbol width.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
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.
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
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.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
QgsPropertyCollection mDataDefinedProperties
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
QgsFields fields() const
Fields of the layer.
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
QgsWkbTypes::GeometryType originalGeometryType() const
Returns the geometry type for the original feature geometry being rendered.
const QgsFeature * feature() const
Returns the current feature being rendered.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
qreal opacity() const
Returns the opacity for the symbol.
Abstract base class for all rendered symbols.
qreal opacity() const
Returns the opacity for the symbol.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
Qgis::SymbolType type() const
Returns the symbol's type.
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.
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...
const QgsMapUnitScale & intervalMapUnitScale() const
Returns the map unit scale for the interval between symbols.
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...
double interval() const
Returns the interval between individual 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...
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.
QgsUnitTypes::RenderUnit outputUnit() const FINAL
Returns the units to use for sizes and widths within the symbol layer.
QgsTemplatedLineSymbolLayerBase(bool rotateSymbol=true, double interval=3)
Constructor for QgsTemplatedLineSymbolLayerBase.
virtual void setSymbolLineAngle(double angle)=0
Sets the line angle modification for the symbol's angle.
void setOffsetAlongLineUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit used for calculating the offset along line for symbols.
void setInterval(double interval)
Sets the interval between individual symbols.
const QgsMapUnitScale & offsetAlongLineMapUnitScale() const
Returns the map unit scale used for calculating the offset in map units along line for symbols.
QgsUnitTypes::RenderUnit averageAngleUnit() const
Returns the unit for the length over which the line's direction is averaged when calculating individu...
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.
QgsUnitTypes::RenderUnit offsetAlongLineUnit() const
Returns the unit used for calculating the offset along line for symbols.
void setPlacements(Qgis::MarkerLinePlacements placements)
Sets the placement of the symbols.
Q_DECL_DEPRECATED void setPlacement(Qgis::MarkerLinePlacement placement)
Sets the placement of the symbols.
QgsUnitTypes::RenderUnit intervalUnit() const
Returns the units for the interval between symbols.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
void setAverageAngleUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the length over which the line's direction is averaged when calculating individual ...
void setIntervalUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the interval between 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 QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
RenderUnit
Rendering size units.
@ RenderUnknownUnit
Mixed or unknown units.
@ RenderMetersInMapUnits
Meters value as Map units.
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
@ RenderPoints
Points (e.g., for font sizes)
@ RenderMillimeters
Millimeters.
@ RenderMapUnits
Map units.
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.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue)
Returns the value corresponding to the given keys of a flag.
QMap< QString, QString > QgsStringMap
QString qgsFlagValueToKeys(const T &value)
Returns the value for the given keys of a flag.
#define DEFAULT_MARKERLINE_INTERVAL
#define DEFAULT_SIMPLELINE_WIDTH
#define DEFAULT_MARKERLINE_ROTATE
#define DEFAULT_SIMPLELINE_PENSTYLE
#define DEFAULT_SIMPLELINE_COLOR
#define QgsDebugMsgLevel(str, level)
QLineF segment(int index, QRectF rect, double radius)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, QgsWkbTypes::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.