39#include <QDomDocument>
45 : mPenStyle( penStyle )
49 mCustomDashVector << 5 << 2;
59 mCustomDashPatternUnit = unit;
60 mDashPatternOffsetUnit = unit;
61 mTrimDistanceStartUnit = unit;
62 mTrimDistanceEndUnit = unit;
86 mCustomDashPatternMapUnitScale = scale;
106 if ( props.contains( QStringLiteral(
"line_color" ) ) )
110 else if ( props.contains( QStringLiteral(
"outline_color" ) ) )
114 else if ( props.contains( QStringLiteral(
"color" ) ) )
119 if ( props.contains( QStringLiteral(
"line_width" ) ) )
121 width = props[QStringLiteral(
"line_width" )].toDouble();
123 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
125 width = props[QStringLiteral(
"outline_width" )].toDouble();
127 else if ( props.contains( QStringLiteral(
"width" ) ) )
130 width = props[QStringLiteral(
"width" )].toDouble();
132 if ( props.contains( QStringLiteral(
"line_style" ) ) )
136 else if ( props.contains( QStringLiteral(
"outline_style" ) ) )
140 else if ( props.contains( QStringLiteral(
"penstyle" ) ) )
146 if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
150 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
154 else if ( props.contains( QStringLiteral(
"width_unit" ) ) )
159 if ( props.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
161 if ( props.contains( QStringLiteral(
"offset" ) ) )
162 l->
setOffset( props[QStringLiteral(
"offset" )].toDouble() );
163 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
165 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
167 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
169 if ( props.contains( QStringLiteral(
"capstyle" ) ) )
172 if ( props.contains( QStringLiteral(
"use_custom_dash" ) ) )
176 if ( props.contains( QStringLiteral(
"customdash" ) ) )
180 if ( props.contains( QStringLiteral(
"customdash_unit" ) ) )
184 if ( props.contains( QStringLiteral(
"customdash_map_unit_scale" ) ) )
189 if ( props.contains( QStringLiteral(
"draw_inside_polygon" ) ) )
194 if ( props.contains( QStringLiteral(
"ring_filter" ) ) )
199 if ( props.contains( QStringLiteral(
"dash_pattern_offset" ) ) )
201 if ( props.contains( QStringLiteral(
"dash_pattern_offset_unit" ) ) )
203 if ( props.contains( QStringLiteral(
"dash_pattern_offset_map_unit_scale" ) ) )
206 if ( props.contains( QStringLiteral(
"trim_distance_start" ) ) )
208 if ( props.contains( QStringLiteral(
"trim_distance_start_unit" ) ) )
210 if ( props.contains( QStringLiteral(
"trim_distance_start_map_unit_scale" ) ) )
212 if ( props.contains( QStringLiteral(
"trim_distance_end" ) ) )
214 if ( props.contains( QStringLiteral(
"trim_distance_end_unit" ) ) )
216 if ( props.contains( QStringLiteral(
"trim_distance_end_map_unit_scale" ) ) )
219 if ( props.contains( QStringLiteral(
"align_dash_pattern" ) ) )
222 if ( props.contains( QStringLiteral(
"tweak_dash_pattern_on_corners" ) ) )
232 return QStringLiteral(
"SimpleLine" );
239 mPen.setColor( penColor );
241 mPen.setWidthF( scaledWidth );
245 const double dashWidthDiv = std::max( 1.0, scaledWidth );
246 if ( mUseCustomDashPattern )
248 mPen.setStyle( Qt::CustomDashLine );
252 QVector<qreal> scaledVector;
253 QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
254 for ( ; it != mCustomDashVector.constEnd(); ++it )
259 mPen.setDashPattern( scaledVector );
263 mPen.setStyle( mPenStyle );
266 if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
271 mPen.setJoinStyle( mPenJoinStyle );
272 mPen.setCapStyle( mPenCapStyle );
277 selColor.setAlphaF( context.
opacity() );
278 mSelPen.setColor( selColor );
295 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
302 if ( mDrawInsidePolygon )
310 if ( mDrawInsidePolygon )
313 QPainterPath clipPath;
314 clipPath.addPolygon( points );
319 for (
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
321 QPolygonF ring = *it;
322 clipPath.addPolygon( ring );
327 p->setClipPath( clipPath, Qt::IntersectClip );
350 for (
const QPolygonF &ring : std::as_const( *rings ) )
366 if ( mDrawInsidePolygon )
382 QPolygonF points = pts;
384 double startTrim = mTrimDistanceStart;
390 double endTrim = mTrimDistanceEnd;
397 double totalLength = -1;
401 startTrim = startTrim * 0.01 * totalLength;
409 if ( totalLength < 0 )
411 endTrim = endTrim * 0.01 * totalLength;
424 mPen.setColor( penColor );
427 applyDataDefinedSymbology( context, mPen, mSelPen,
offset );
429 const QPen pen = context.
selected() ? mSelPen : mPen;
431 if ( !pen.dashPattern().isEmpty() )
434 const QVector<double> pattern = pen.dashPattern();
435 bool foundNonNull =
false;
436 for (
int i = 0; i < pattern.size(); ++i )
448 p->setBrush( Qt::NoBrush );
451 std::unique_ptr< QgsScopedQPainterState > painterState;
452 if ( points.size() <= 2 &&
455 ( p->renderHints() & QPainter::Antialiasing ) )
457 painterState = std::make_unique< QgsScopedQPainterState >( p );
458 p->setRenderHint( QPainter::Antialiasing,
false );
461 const bool applyPatternTweaks = mAlignDashPattern
462 && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
463 && pen.dashOffset() == 0;
467 if ( applyPatternTweaks )
469 drawPathWithDashPatternTweaks( p, points, pen );
475 path.addPolygon( points );
490 for (
const QPolygonF &part : mline )
492 if ( applyPatternTweaks )
494 drawPathWithDashPatternTweaks( p, part, pen );
500 path.addPolygon( part );
511 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
517 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
520 map[QStringLiteral(
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
524 map[QStringLiteral(
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
527 map[QStringLiteral(
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
530 map[QStringLiteral(
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
533 map[QStringLiteral(
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
534 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
535 map[QStringLiteral(
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
536 map[QStringLiteral(
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral(
"1" ) : QStringLiteral(
"0" );
575 if ( mPenStyle == Qt::NoPen )
578 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
579 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
580 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
581 element.appendChild( symbolizerElem );
587 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
588 symbolizerElem.appendChild( strokeElem );
590 Qt::PenStyle
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
599 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
602 symbolizerElem.appendChild( perpOffsetElem );
608 if ( mUseCustomDashPattern )
611 mPen.color(), mPenJoinStyle,
612 mPenCapStyle,
mOffset, &mCustomDashVector );
625 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
626 if ( strokeElem.isNull() )
643 QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
644 if ( !perpOffsetElem.isNull() )
647 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
652 double scaleFactor = 1.0;
653 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
668void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen,
double &offset )
674 bool hasStrokeWidthExpression =
false;
681 pen.setWidthF( scaledWidth );
682 selPen.setWidthF( scaledWidth );
683 hasStrokeWidthExpression =
true;
692 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
693 pen.setColor( penColor );
707 const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
711 QVector<qreal> dashVector;
715 QStringList dashList = exprVal.toString().split(
';' );
716 QStringList::const_iterator dashIt = dashList.constBegin();
717 for ( ; dashIt != dashList.constEnd(); ++dashIt )
721 pen.setDashPattern( dashVector );
728 QVector<qreal> scaledVector;
729 for (
double v : std::as_const( mCustomDashVector ) )
734 mPen.setDashPattern( scaledVector );
738 double patternOffset = mDashPatternOffset;
774void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter,
const QPolygonF &points, QPen pen )
const
776 if ( pen.dashPattern().empty() || points.size() < 2 )
779 QVector< qreal > sourcePattern = pen.dashPattern();
780 const double dashWidthDiv = std::max( 1.0001, pen.widthF() );
782 for (
int i = 0; i < sourcePattern.size(); ++ i )
783 sourcePattern[i] *= pen.widthF();
785 if ( pen.widthF() <= 1.0 )
786 pen.setWidthF( 1.0001 );
788 QVector< qreal > buffer;
789 QPolygonF bufferedPoints;
790 QPolygonF previousSegmentBuffer;
795 auto ptIt = points.constBegin();
796 double totalBufferLength = 0;
797 int patternIndex = 0;
798 double currentRemainingDashLength = 0;
799 double currentRemainingGapLength = 0;
801 auto compressPattern = [](
const QVector< qreal > &buffer ) -> QVector< qreal >
803 QVector< qreal > result;
804 result.reserve( buffer.size() );
805 for (
auto it = buffer.begin(); it != buffer.end(); )
809 while ( dash == 0 && !result.empty() )
811 result.last() += gap;
813 if ( it == buffer.end() )
818 while ( gap == 0 && it != buffer.end() )
823 result << dash << gap;
828 double currentBufferLineLength = 0;
829 auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength, ¤tBufferLineLength, &totalBufferLength,
830 dashWidthDiv, &compressPattern]( QPointF * nextPoint )
832 if ( buffer.empty() || bufferedPoints.size() < 2 )
837 if ( currentRemainingDashLength )
840 buffer << currentRemainingDashLength << 0.0;
841 totalBufferLength += currentRemainingDashLength;
843 QVector< qreal > compressed = compressPattern( buffer );
844 if ( !currentRemainingDashLength )
847 totalBufferLength -= compressed.last();
848 compressed.last() = 0;
852 const double scaleFactor = currentBufferLineLength / totalBufferLength;
854 bool shouldFlushPreviousSegmentBuffer =
false;
856 if ( !previousSegmentBuffer.empty() )
860 if ( !firstDashSubstring.empty() )
866 compressed = compressed.mid( 2 );
867 shouldFlushPreviousSegmentBuffer = !compressed.empty();
870 if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
872 QPen adjustedPen = pen;
873 adjustedPen.setStyle( Qt::SolidLine );
874 painter->setPen( adjustedPen );
876 path.addPolygon( previousSegmentBuffer );
877 painter->drawPath( path );
878 previousSegmentBuffer.clear();
881 double finalDash = 0;
888 if ( !compressed.empty() )
890 finalDash = compressed.at( compressed.size() - 2 );
891 const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
893 const QPolygonF thisPoints = bufferedPoints;
899 previousSegmentBuffer << bufferedPoints;
903 currentBufferLineLength = 0;
904 currentRemainingDashLength = 0;
905 currentRemainingGapLength = 0;
906 totalBufferLength = 0;
909 if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
911 QPen adjustedPen = pen;
912 if ( !compressed.empty() )
915 compressed = compressed.mid( 0, 32 );
916 std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
917 adjustedPen.setDashPattern( compressed );
921 adjustedPen.setStyle( Qt::SolidLine );
924 painter->setPen( adjustedPen );
926 path.addPolygon( bufferedPoints );
927 painter->drawPath( path );
930 bufferedPoints.clear();
936 bufferedPoints << p2;
937 for ( ; ptIt != points.constEnd(); ++ptIt )
945 double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
946 currentBufferLineLength += remainingSegmentDistance;
950 if ( currentRemainingDashLength > 0 )
953 if ( remainingSegmentDistance >= currentRemainingDashLength )
956 buffer << currentRemainingDashLength << 0.0;
957 totalBufferLength += currentRemainingDashLength;
958 remainingSegmentDistance -= currentRemainingDashLength;
960 currentRemainingDashLength = 0.0;
961 currentRemainingGapLength = sourcePattern.at( patternIndex );
966 buffer << remainingSegmentDistance << 0.0;
967 totalBufferLength += remainingSegmentDistance;
968 currentRemainingDashLength -= remainingSegmentDistance;
972 if ( currentRemainingGapLength > 0 )
975 if ( remainingSegmentDistance >= currentRemainingGapLength )
978 buffer << 0.0 << currentRemainingGapLength;
979 totalBufferLength += currentRemainingGapLength;
980 remainingSegmentDistance -= currentRemainingGapLength;
981 currentRemainingGapLength = 0.0;
987 buffer << 0.0 << remainingSegmentDistance;
988 totalBufferLength += remainingSegmentDistance;
989 currentRemainingGapLength -= remainingSegmentDistance;
994 if ( patternIndex >= sourcePattern.size() )
997 const double nextPatternDashLength = sourcePattern.at( patternIndex );
998 const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
999 if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
1001 buffer << nextPatternDashLength << nextPatternGapLength;
1002 remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
1003 totalBufferLength += nextPatternDashLength + nextPatternGapLength;
1006 else if ( nextPatternDashLength <= remainingSegmentDistance )
1009 buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
1010 totalBufferLength += remainingSegmentDistance;
1011 currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
1012 currentRemainingDashLength = 0;
1019 buffer << remainingSegmentDistance << 0.0;
1020 totalBufferLength += remainingSegmentDistance;
1021 currentRemainingGapLength = 0;
1022 currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
1027 bufferedPoints << p1;
1028 if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
1030 QPointF nextPoint = *( ptIt + 1 );
1036 flushBuffer( &nextPoint );
1037 bufferedPoints << p1;
1040 if ( patternIndex % 2 == 1 )
1044 currentRemainingDashLength = sourcePattern.at( patternIndex );
1051 flushBuffer(
nullptr );
1052 if ( !previousSegmentBuffer.empty() )
1054 QPen adjustedPen = pen;
1055 adjustedPen.setStyle( Qt::SolidLine );
1056 painter->setPen( adjustedPen );
1058 path.addPolygon( previousSegmentBuffer );
1059 painter->drawPath( path );
1060 previousSegmentBuffer.clear();
1066 if ( mDrawInsidePolygon )
1080 unit = mCustomDashPatternUnit;
1081 return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
1118 return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
1123 return mAlignDashPattern;
1133 return mPatternCartographicTweakOnSharpCorners;
1138 mPatternCartographicTweakOnSharpCorners =
enabled;
1166 MyLine( QPointF p1, QPointF p2 )
1167 : mVertical( false )
1168 , mIncreasing( false )
1180 mIncreasing = ( p2.y() > p1.y() );
1185 mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
1186 mIncreasing = ( p2.x() > p1.x() );
1190 double x = ( p2.x() - p1.x() );
1191 double y = ( p2.y() - p1.y() );
1192 mLength = std::sqrt( x * x + y * y );
1198 double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
1206 QPointF diffForInterval(
double interval )
1209 return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
1211 double alpha = std::atan( mT );
1212 double dx = std::cos( alpha ) * interval;
1213 double dy = std::sin( alpha ) * interval;
1214 return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
1217 double length()
const {
return mLength; }
1232 : mRotateSymbols( rotateSymbol )
1233 , mInterval( interval )
1271 if ( mRenderingFeature )
1275 mFeatureSymbolOpacity = context.
opacity();
1276 mCurrentFeatureIsSelected = context.
selected();
1294 QString placementString = exprVal.toString();
1295 if ( placementString.compare( QLatin1String(
"interval" ), Qt::CaseInsensitive ) == 0 )
1299 else if ( placementString.compare( QLatin1String(
"vertex" ), Qt::CaseInsensitive ) == 0 )
1303 else if ( placementString.compare( QLatin1String(
"innervertices" ), Qt::CaseInsensitive ) == 0 )
1307 else if ( placementString.compare( QLatin1String(
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
1311 else if ( placementString.compare( QLatin1String(
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
1315 else if ( placementString.compare( QLatin1String(
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
1319 else if ( placementString.compare( QLatin1String(
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
1323 else if ( placementString.compare( QLatin1String(
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
1336 double averageOver = mAverageAngleLength;
1347 renderPolylineInterval( points, context, averageOver );
1349 renderPolylineCentral( points, context, averageOver );
1353 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1356 mHasRenderedFirstPart = mRenderingFeature;
1372 for (
int part = 0; part < mline.count(); ++part )
1374 const QPolygonF &points2 = mline[ part ];
1377 renderPolylineInterval( points2, context, averageOver );
1379 renderPolylineCentral( points2, context, averageOver );
1387 && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
1390 mHasRenderedFirstPart = mRenderingFeature;
1410 std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
1440 for (
int i = 0; i < rings->size(); ++i )
1473 mIntervalUnit = unit;
1474 mOffsetAlongLineUnit = unit;
1475 mAverageAngleLengthUnit = unit;
1500 map[QStringLiteral(
"rotate" )] = (
rotateSymbols() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1501 map[QStringLiteral(
"interval" )] = QString::number(
interval() );
1502 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
1503 map[QStringLiteral(
"offset_along_line" )] = QString::number(
offsetAlongLine() );
1510 map[QStringLiteral(
"average_angle_length" )] = QString::number( mAverageAngleLength );
1516 map[QStringLiteral(
"ring_filter" )] = QString::number(
static_cast< int >(
mRingFilter ) );
1517 map[QStringLiteral(
"place_on_every_part" )] = mPlaceOnEveryPart;
1523 return mPlaceOnEveryPart
1531 mRenderingFeature =
true;
1532 mHasRenderedFirstPart =
false;
1537 mRenderingFeature =
false;
1545 renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
1546 mFeatureSymbolOpacity = 1;
1573 if (
properties.contains( QStringLiteral(
"offset" ) ) )
1577 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
1581 if (
properties.contains( QStringLiteral(
"interval_unit" ) ) )
1585 if (
properties.contains( QStringLiteral(
"offset_along_line" ) ) )
1589 if (
properties.contains( QStringLiteral(
"offset_along_line_unit" ) ) )
1593 if (
properties.contains( ( QStringLiteral(
"offset_along_line_map_unit_scale" ) ) ) )
1598 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1602 if (
properties.contains( QStringLiteral(
"interval_map_unit_scale" ) ) )
1607 if (
properties.contains( QStringLiteral(
"average_angle_length" ) ) )
1611 if (
properties.contains( QStringLiteral(
"average_angle_unit" ) ) )
1615 if (
properties.contains( ( QStringLiteral(
"average_angle_map_unit_scale" ) ) ) )
1620 if (
properties.contains( QStringLiteral(
"placement" ) ) )
1622 if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"vertex" ) )
1624 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"lastvertex" ) )
1626 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"firstvertex" ) )
1628 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"centralpoint" ) )
1630 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"curvepoint" ) )
1632 else if (
properties[QStringLiteral(
"placement" )] == QLatin1String(
"segmentcenter" ) )
1637 else if (
properties.contains( QStringLiteral(
"placements" ) ) )
1643 if (
properties.contains( QStringLiteral(
"ring_filter" ) ) )
1653void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageOver )
1655 if ( points.isEmpty() )
1658 double lengthLeft = 0;
1690 if ( painterUnitInterval < 0 )
1693 double painterUnitOffsetAlongLine = 0;
1696 double totalLength = -1;
1717 if ( points.isClosed() )
1719 if ( painterUnitOffsetAlongLine > 0 )
1721 if ( totalLength < 0 )
1723 painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
1725 else if ( painterUnitOffsetAlongLine < 0 )
1727 if ( totalLength < 0 )
1729 painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
1741 lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
1743 if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
1745 QVector< QPointF > angleStartPoints;
1746 QVector< QPointF > symbolPoints;
1747 QVector< QPointF > angleEndPoints;
1755 collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
1757 if ( symbolPoints.empty() )
1763 if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
1766 symbolPoints.pop_back();
1769 angleEndPoints.reserve( symbolPoints.size() );
1770 angleStartPoints.reserve( symbolPoints.size() );
1771 if ( averageOver <= painterUnitOffsetAlongLine )
1773 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
1777 collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
1779 collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
1782 for (
int i = 0; i < symbolPoints.size(); ++ i )
1787 const QPointF pt = symbolPoints[i];
1788 const QPointF startPt = angleStartPoints[i];
1789 const QPointF endPt = angleEndPoints[i];
1791 MyLine l( startPt, endPt );
1806 QPointF lastPt = points[0];
1807 for (
int i = 1; i < points.count(); ++i )
1812 const QPointF &pt = points[i];
1818 MyLine l( lastPt, pt );
1819 QPointF diff = l.diffForInterval( painterUnitInterval );
1823 double c = 1 - lengthLeft / painterUnitInterval;
1825 lengthLeft += l.length();
1834 while ( lengthLeft > painterUnitInterval )
1838 lengthLeft -= painterUnitInterval;
1850static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
1853 double a1 = MyLine( prevPt, pt ).angle();
1854 double a2 = MyLine( pt, nextPt ).angle();
1855 double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
1857 return std::atan2( unitY, unitX );
1862 if ( points.isEmpty() )
1867 int i = -1, maxCount = 0;
1868 bool isRing =
false;
1882 double totalLength = -1;
1902 if ( points.isClosed() )
1906 if ( totalLength < 0 )
1912 if ( totalLength < 0 )
1985 i = points.count() - 1;
1987 maxCount = points.count();
1995 maxCount = points.count() - 1;
2003 maxCount = points.count();
2004 if ( points.first() == points.last() )
2021 renderOffsetVertexAlongLine( points, i, distance, context,
placement );
2028 prevPoint = points.at( 0 );
2030 QPointF symbolPoint;
2031 for ( ; i < maxCount; ++i )
2042 QPointF currentPoint = points.at( i );
2043 symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
2044 0.5 * ( currentPoint.y() + prevPoint.y() ) );
2047 double angle = std::atan2( currentPoint.y() - prevPoint.y(),
2048 currentPoint.x() - prevPoint.x() );
2051 prevPoint = currentPoint;
2055 symbolPoint = points.at( i );
2059 double angle = markerAngle( points, isRing, i );
2064 mFinalVertex = symbolPoint;
2070double QgsTemplatedLineSymbolLayerBase::markerAngle(
const QPolygonF &points,
bool isRing,
int vertex )
2073 const QPointF &pt = points[vertex];
2075 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
2077 int prevIndex = vertex - 1;
2078 int nextIndex = vertex + 1;
2080 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
2082 prevIndex = points.count() - 2;
2086 QPointF prevPoint, nextPoint;
2087 while ( prevIndex >= 0 )
2089 prevPoint = points[ prevIndex ];
2090 if ( prevPoint != pt )
2097 while ( nextIndex < points.count() )
2099 nextPoint = points[ nextIndex ];
2100 if ( nextPoint != pt )
2107 if ( prevIndex >= 0 && nextIndex < points.count() )
2109 angle = _averageAngle( prevPoint, pt, nextPoint );
2116 while ( vertex < points.size() - 1 )
2118 const QPointF &nextPt = points[vertex + 1];
2121 angle = MyLine( pt, nextPt ).angle();
2130 while ( vertex >= 1 )
2132 const QPointF &prevPt = points[vertex - 1];
2135 angle = MyLine( prevPt, pt ).angle();
2147 if ( points.isEmpty() )
2156 bool isRing =
false;
2157 if ( points.first() == points.last() )
2159 double angle = markerAngle( points, isRing, vertex );
2162 mFinalVertex = points[vertex];
2168 int pointIncrement = distance > 0 ? 1 : -1;
2169 QPointF previousPoint = points[vertex];
2170 int startPoint = distance > 0 ? std::min( vertex + 1,
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
2171 int endPoint = distance > 0 ? points.count() - 1 : 0;
2172 double distanceLeft = std::fabs( distance );
2174 for (
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
2176 const QPointF &pt = points[i];
2178 if ( previousPoint == pt )
2182 MyLine l( previousPoint, pt );
2184 if ( distanceLeft < l.length() )
2187 QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
2193 mFinalVertex = markerPoint;
2199 distanceLeft -= l.length();
2206void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints(
const QVector<QPointF> &p, QVector<QPointF> &dest,
double intervalPainterUnits,
double initialOffset,
double initialLag,
int numberPointsRequired )
2211 QVector< QPointF > points = p;
2212 const bool closedRing = points.first() == points.last();
2214 double lengthLeft = initialOffset;
2216 double initialLagLeft = initialLag > 0 ? -initialLag : 1;
2217 if ( initialLagLeft < 0 && closedRing )
2220 QPointF lastPt = points.constLast();
2221 QVector< QPointF > pseudoPoints;
2222 for (
int i = points.count() - 2; i > 0; --i )
2224 if ( initialLagLeft >= 0 )
2229 const QPointF &pt = points[i];
2234 MyLine l( lastPt, pt );
2235 initialLagLeft += l.length();
2240 std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
2242 points = pseudoPoints;
2247 while ( initialLagLeft < 0 )
2249 dest << points.constFirst();
2250 initialLagLeft += intervalPainterUnits;
2253 if ( initialLag > 0 )
2255 lengthLeft += intervalPainterUnits - initialLagLeft;
2258 QPointF lastPt = points[0];
2259 for (
int i = 1; i < points.count(); ++i )
2261 const QPointF &pt = points[i];
2265 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2274 MyLine l( lastPt, pt );
2275 QPointF diff = l.diffForInterval( intervalPainterUnits );
2279 double c = 1 - lengthLeft / intervalPainterUnits;
2281 lengthLeft += l.length();
2284 while ( lengthLeft > intervalPainterUnits ||
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
2288 lengthLeft -= intervalPainterUnits;
2291 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2296 if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
2300 if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2307 if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
2310 while ( dest.size() < numberPointsRequired )
2311 dest << points.constLast();
2315void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral(
const QPolygonF &points,
QgsSymbolRenderContext &context,
double averageAngleOver )
2317 if ( !points.isEmpty() )
2321 QPolygonF::const_iterator it = points.constBegin();
2323 for ( ++it; it != points.constEnd(); ++it )
2325 length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2326 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2332 const double midPoint = length / 2;
2335 double thisSymbolAngle = 0;
2337 if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
2339 QVector< QPointF > angleStartPoints;
2340 QVector< QPointF > symbolPoints;
2341 QVector< QPointF > angleEndPoints;
2343 collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
2344 collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
2345 collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
2347 pt = symbolPoints.at( 1 );
2348 MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
2349 thisSymbolAngle = l.angle();
2354 it = points.constBegin();
2356 qreal last_at = 0, next_at = 0;
2359 for ( ++it; it != points.constEnd(); ++it )
2362 next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
2363 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
2364 if ( next_at >= midPoint )
2372 MyLine l( last, next );
2373 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
2374 pt = last + ( next - last ) * k;
2375 thisSymbolAngle = l.angle();
2427 if ( props.contains( QStringLiteral(
"interval" ) ) )
2428 interval = props[QStringLiteral(
"interval" )].toDouble();
2429 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2430 rotate = ( props[QStringLiteral(
"rotate" )].toString() == QLatin1String(
"1" ) );
2432 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate,
interval );
2439 return QStringLiteral(
"MarkerLine" );
2456 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2459 mMarker->setRenderHints( hints );
2472 std::unique_ptr< QgsMarkerLineSymbolLayer > x = std::make_unique< QgsMarkerLineSymbolLayer >(
rotateSymbols(),
interval() );
2479 for (
int i = 0; i <
mMarker->symbolLayerCount(); i++ )
2481 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:LineSymbolizer" ) );
2482 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2483 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2484 element.appendChild( symbolizerElem );
2514 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2515 symbolizerElem.appendChild( strokeElem );
2518 QDomElement graphicStrokeElem = doc.createElement( QStringLiteral(
"se:GraphicStroke" ) );
2519 strokeElem.appendChild( graphicStrokeElem );
2524 markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
2528 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) ) );
2532 graphicStrokeElem.appendChild( doc.createComment( QStringLiteral(
"Missing marker line symbol layer. Skip it." ) ) );
2535 if ( !gap.isEmpty() )
2537 QDomElement gapElem = doc.createElement( QStringLiteral(
"se:Gap" ) );
2539 graphicStrokeElem.appendChild( gapElem );
2544 QDomElement perpOffsetElem = doc.createElement( QStringLiteral(
"se:PerpendicularOffset" ) );
2547 symbolizerElem.appendChild( perpOffsetElem );
2556 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2557 if ( strokeElem.isNull() )
2560 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
2561 if ( graphicStrokeElem.isNull() )
2569 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
2571 if ( it.key() == QLatin1String(
"placement" ) )
2573 if ( it.value() == QLatin1String(
"points" ) )
2575 else if ( it.value() == QLatin1String(
"firstPoint" ) )
2577 else if ( it.value() == QLatin1String(
"lastPoint" ) )
2579 else if ( it.value() == QLatin1String(
"centralPoint" ) )
2582 else if ( it.value() == QLatin1String(
"rotateMarker" ) )
2588 std::unique_ptr< QgsMarkerSymbol > marker;
2602 QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"Gap" ) );
2603 if ( !gapElem.isNull() )
2606 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
2612 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral(
"PerpendicularOffset" ) );
2613 if ( !perpOffsetElem.isNull() )
2616 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
2621 double scaleFactor = 1.0;
2622 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
2645 mMarker->setDataDefinedSize( property );
2652 const double prevOpacity =
mMarker->opacity();
2655 mMarker->setOpacity( prevOpacity );
2678 mMarker->renderPoint( point, feature, context, layer, selected );
2690 return mMarker->size( context );
2696 mMarker->setOutputUnit( unit );
2713 attr.unite(
mMarker->usedAttributes( context ) );
2728 return (
mMarker->size( context ) / 2.0 ) +
2750 if ( props.contains( QStringLiteral(
"interval" ) ) )
2751 interval = props[QStringLiteral(
"interval" )].toDouble();
2752 if ( props.contains( QStringLiteral(
"rotate" ) ) )
2753 rotate = ( props[QStringLiteral(
"rotate" )] == QLatin1String(
"1" ) );
2755 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >( rotate,
interval );
2757 if ( props.contains( QStringLiteral(
"hash_angle" ) ) )
2759 x->setHashAngle( props[QStringLiteral(
"hash_angle" )].toDouble() );
2762 if ( props.contains( QStringLiteral(
"hash_length" ) ) )
2763 x->setHashLength( props[QStringLiteral(
"hash_length" )].toDouble() );
2765 if ( props.contains( QStringLiteral(
"hash_length_unit" ) ) )
2768 if ( props.contains( QStringLiteral(
"hash_length_map_unit_scale" ) ) )
2776 return QStringLiteral(
"HashLine" );
2782 Qgis::SymbolRenderHints hints = Qgis::SymbolRenderHints();
2785 mHashSymbol->setRenderHints( hints );
2798 map[ QStringLiteral(
"hash_angle" ) ] = QString::number( mHashAngle );
2800 map[QStringLiteral(
"hash_length" )] = QString::number( mHashLength );
2809 std::unique_ptr< QgsHashedLineSymbolLayer > x = std::make_unique< QgsHashedLineSymbolLayer >(
rotateSymbols(),
interval() );
2811 x->setHashAngle( mHashAngle );
2812 x->setHashLength( mHashLength );
2813 x->setHashLengthUnit( mHashLengthUnit );
2814 x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
2820 mHashSymbol->setColor(
color );
2826 return mHashSymbol ? mHashSymbol->color() :
mColor;
2831 return mHashSymbol.get();
2842 mHashSymbol.reset(
static_cast<QgsLineSymbol *
>( symbol ) );
2843 mColor = mHashSymbol->color();
2849 mHashLength =
width;
2864 return ( mHashSymbol->width( context ) / 2.0 )
2872 mHashSymbol->setOutputUnit( unit );
2879 attr.unite( mHashSymbol->usedAttributes( context ) );
2887 if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
2896 mHashSymbol->setDataDefinedWidth( property );
2909 || ( mHashSymbol && mHashSymbol->usesMapUnits() );
2914 mSymbolLineAngle =
angle;
2919 return mSymbolAngle;
2924 mSymbolAngle =
angle;
2929 double lineLength = mHashLength;
2935 const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
2949 points << QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
2954 mHashSymbol->renderPolyline( points, feature, context, layer, selected );
2971 const double prevOpacity = mHashSymbol->opacity();
2972 mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
2974 mHashSymbol->setOpacity( prevOpacity );
2993 QPolygonF offsetPoints;
2996 renderLine( points, context, patternThickness, patternLength, brush );
3005 renderLine( part, context, patternThickness, patternLength, brush );
3010void QgsAbstractBrushedLineSymbolLayer::renderLine(
const QPolygonF &points,
QgsSymbolRenderContext &context,
const double lineThickness,
3011 const double patternLength,
const QBrush &sourceBrush )
3017 QBrush brush = sourceBrush;
3022 QPolygonF inputPoints;
3023 inputPoints.reserve( points.size() );
3025 double minX = std::numeric_limits< double >::max();
3026 double minY = std::numeric_limits< double >::max();
3027 double maxX = std::numeric_limits< double >::lowest();
3028 double maxY = std::numeric_limits< double >::lowest();
3030 for (
const QPointF &pt : std::as_const( points ) )
3037 minX = std::min( minX, pt.x() );
3038 minY = std::min( minY, pt.y() );
3039 maxX = std::max( maxX, pt.x() );
3040 maxY = std::max( maxY, pt.y() );
3043 if ( inputPoints.size() < 2 )
3047 constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
3049 constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
3052 const int imageWidth =
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3053 const int imageHeight =
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
3055 const bool isClosedLine =
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
3056 &&
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
3058 QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
3059 if ( temporaryImage.isNull() )
3068 temporaryImage.fill( Qt::transparent );
3091 QPainterPathStroker stroker;
3092 stroker.setWidth( lineThickness );
3093 stroker.setCapStyle( cap );
3094 stroker.setJoinStyle( join );
3097 path.addPolygon( inputPoints );
3098 const QPainterPath stroke = stroker.createStroke( path ).simplified();
3101 QPainter imagePainter;
3102 imagePainter.begin( &temporaryImage );
3104 imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
3106 imagePainter.setClipPath( stroke, Qt::IntersectClip );
3107 imagePainter.setPen( Qt::NoPen );
3109 QPointF segmentStartPoint = inputPoints.at( 0 );
3112 double progressThroughImage = 0;
3114 QgsPoint prevSegmentPolygonEndLeft;
3115 QgsPoint prevSegmentPolygonEndRight;
3121 for (
int i = 1; i < inputPoints.size(); ++i )
3126 const QPointF segmentEndPoint = inputPoints.at( i );
3128 segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
3131 QgsPoint thisSegmentPolygonEndLeft;
3132 QgsPoint thisSegmentPolygonEndRight;
3134 QgsPoint thisSegmentPolygonEndLeftForPainter;
3135 QgsPoint thisSegmentPolygonEndRightForPainter;
3143 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3145 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3146 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3150 const double lastSegmentAngleDegrees = 180.0 / M_PI *
QgsGeometryUtils::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
3151 segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
3154 const QgsPoint lastSegmentStartPointLeft =
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3155 const QgsPoint lastSegmentEndPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
3156 const QgsPoint lastSegmentStartPointRight =
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3157 const QgsPoint lastSegmentEndPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
3163 bool isIntersection =
false;
3165 if ( !isIntersection )
3166 prevSegmentPolygonEndLeft = startPointLeft;
3167 isIntersection =
false;
3168 QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3169 if ( !isIntersection )
3170 prevSegmentPolygonEndRight = startPointRight;
3172 startLinePolygonLeft = prevSegmentPolygonEndLeft;
3173 startLinePolygonRight = prevSegmentPolygonEndRight;
3177 prevSegmentPolygonEndLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3178 if ( cap != Qt::PenCapStyle::FlatCap )
3179 prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3180 prevSegmentPolygonEndRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3181 if ( cap != Qt::PenCapStyle::FlatCap )
3182 prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
3186 if ( i < inputPoints.size() - 1 )
3191 const QgsPoint startPointLeft =
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3193 const QgsPoint startPointRight =
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3194 const QgsPoint endPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3199 inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
3202 const QgsPoint nextSegmentStartPointLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3203 const QgsPoint nextSegmentEndPointLeft =
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
3204 const QgsPoint nextSegmentStartPointRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3205 const QgsPoint nextSegmentEndPointRight =
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
3211 bool isIntersection =
false;
3213 if ( !isIntersection )
3214 thisSegmentPolygonEndLeft = endPointLeft;
3215 isIntersection =
false;
3216 QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8,
true );
3217 if ( !isIntersection )
3218 thisSegmentPolygonEndRight = endPointRight;
3220 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3221 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3229 thisSegmentPolygonEndLeft = startLinePolygonLeft;
3230 thisSegmentPolygonEndRight = startLinePolygonRight;
3232 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3233 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
3237 thisSegmentPolygonEndLeft =
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
3238 if ( cap != Qt::PenCapStyle::FlatCap )
3239 thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3240 thisSegmentPolygonEndRight =
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
3241 if ( cap != Qt::PenCapStyle::FlatCap )
3242 thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
3244 thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
3245 thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
3251 QTransform brushTransform;
3252 brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
3253 brushTransform.rotate( -segmentAngleDegrees );
3254 if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
3258 brushTransform.translate( -( lineThickness / 2 ), 0 );
3260 brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
3262 brush.setTransform( brushTransform );
3263 imagePainter.setBrush( brush );
3266 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3267 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3268 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3269 << prevSegmentPolygonEndRight.
toQPointF()
3270 << prevSegmentPolygonEndLeft.
toQPointF() );
3273 imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
3274 imagePainter.setBrush( Qt::NoBrush );
3275 imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
3276 << thisSegmentPolygonEndLeftForPainter.
toQPointF()
3277 << thisSegmentPolygonEndRightForPainter.
toQPointF()
3278 << prevSegmentPolygonEndRight.
toQPointF()
3279 << prevSegmentPolygonEndLeft.
toQPointF() );
3280 imagePainter.setPen( Qt::NoPen );
3285 progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
3286 + std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
3287 + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 );
3288 progressThroughImage = fmod( progressThroughImage, patternLength );
3291 segmentStartPoint = segmentEndPoint;
3292 prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
3293 prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
3301 p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
3302 minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
3319 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique<QgsRasterLineSymbolLayer>();
3321 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3323 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3325 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3329 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3334 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
3335 res->setPath(
properties[QStringLiteral(
"imageFile" )].toString() );
3337 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3339 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3341 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3345 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3350 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3352 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3355 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
3357 res->setOpacity(
properties[QStringLiteral(
"alpha" )].toDouble() );
3360 return res.release();
3367 map[QStringLiteral(
"imageFile" )] =
mPath;
3369 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3376 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3380 map[QStringLiteral(
"alpha" )] = QString::number(
mOpacity );
3387 std::unique_ptr< QgsRasterLineSymbolLayer > res = std::make_unique< QgsRasterLineSymbolLayer >(
mPath );
3399 return res.release();
3404 const QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
3405 if ( it !=
properties.end() && it.value().type() == QVariant::String )
3421 return QStringLiteral(
"RasterLine" );
3431 bool cached =
false;
3433 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3434 static_cast< int >( std::ceil( scaledHeight ) ) ),
3459 double strokeWidth =
mWidth;
3476 bool cached =
false;
3478 QSize(
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
3479 static_cast< int >( std::ceil( scaledHeight ) ) ),
3488 const QBrush brush( sourceImage );
3558 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique<QgsLineburstSymbolLayer>();
3560 if (
properties.contains( QStringLiteral(
"line_width" ) ) )
3562 res->setWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
3564 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
3568 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
3573 if (
properties.contains( QStringLiteral(
"offset" ) ) )
3575 res->setOffset(
properties[QStringLiteral(
"offset" )].toDouble() );
3577 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
3581 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
3586 if (
properties.contains( QStringLiteral(
"joinstyle" ) ) )
3588 if (
properties.contains( QStringLiteral(
"capstyle" ) ) )
3591 if (
properties.contains( QStringLiteral(
"color_type" ) ) )
3594 if (
properties.contains( QStringLiteral(
"color" ) ) )
3598 if (
properties.contains( QStringLiteral(
"gradient_color2" ) ) )
3613 return res.release();
3620 map[QStringLiteral(
"line_width" )] = QString::number(
mWidth );
3627 map[QStringLiteral(
"offset" )] = QString::number(
mOffset );
3633 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
3636#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
3648 std::unique_ptr< QgsLineburstSymbolLayer > res = std::make_unique< QgsLineburstSymbolLayer >();
3664 return res.release();
3669 return QStringLiteral(
"Lineburst" );
3685 double strokeWidth =
mWidth;
3704 color1.setAlphaF( context.
opacity() * color1.alphaF() );
3715 QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
3727 gradient.setColorAt( 0.0, color1 );
3728 gradient.setColorAt( 1.0,
color2 );
3730 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, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
static void overlayColor(QImage &image, const QColor &color)
Overlays a color onto an image.
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.
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
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).
QgsExpressionContext & expressionContext()
Gets the expression context.
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
const QgsVectorSimplifyMethod & vectorSimplifyMethod() const
Returns the simplification settings to use when rendering vector layers.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QColor selectionColor() const
Returns the color to use when rendering selected features.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
const QgsAbstractGeometry * geometry() const
Returns pointer to the unsegmentized geometry.
Scoped object for saving and restoring a QPainter object's state.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void setDrawInsidePolygon(bool drawInsidePolygon)
Sets whether the line should only be drawn inside polygons, and any portion of the line which falls o...
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QgsMapUnitScale mapUnitScale() const override
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...
QVector< qreal > customDashVector() const
Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the outline of polygon, using the given render context.
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 ...
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 QgsUnitTypes::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static QString encodeColor(const QColor &color)
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static 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 QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
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.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
const QgsFeature * feature() const
Returns the current feature being rendered.
QgsFields fields() const
Fields of the layer.
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style.
QgsWkbTypes::GeometryType originalGeometryType() const
Returns the geometry type for the original feature geometry 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.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for all rendered symbols.
qreal opacity() const
Returns the opacity for the symbol.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
Qgis::SymbolType type() const
Returns the symbol's type.
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...
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...
const QgsMapUnitScale & intervalMapUnitScale() const
Returns the map unit scale for the interval between symbols.
double offsetAlongLine() const
Returns the offset along the line for the symbol placement.
~QgsTemplatedLineSymbolLayerBase() override
void copyTemplateSymbolProperties(QgsTemplatedLineSymbolLayerBase *destLayer) const
Copies all common properties of this layer to another templated symbol layer.
Qgis::MarkerLinePlacements placements() const
Returns the placement of the symbols.
void setOffsetAlongLine(double offsetAlongLine)
Sets the the offset along the line for the symbol placement.
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) FINAL
Renders the line symbol layer along the outline of polygon, using the given render context.
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.
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 setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
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.
const QgsMapUnitScale & offsetAlongLineMapUnitScale() const
Returns the map unit scale used for calculating the offset in map units along line for symbols.
virtual void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false)=0
Renders the templated symbol at the specified point, using the given render context.
void setIntervalMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the interval between symbols.
void setOffsetAlongLineMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale used for calculating the offset in map units along line for symbols.
void setAverageAngleLength(double length)
Sets the length of line over which the line's direction is averaged when calculating individual symbo...
static Q_INVOKABLE 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.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QMap< QString, QString > QgsStringMap
#define DEFAULT_MARKERLINE_INTERVAL
#define DEFAULT_SIMPLELINE_WIDTH
#define DEFAULT_MARKERLINE_ROTATE
#define DEFAULT_SIMPLELINE_PENSTYLE
#define DEFAULT_SIMPLELINE_COLOR
#define QgsDebugMsgLevel(str, level)
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.