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" );
 
 
  244  mPen.setColor( penColor );
 
  246  mPen.setWidthF( scaledWidth );
 
  250  const double dashWidthDiv = std::max( 1.0, scaledWidth );
 
  251  if ( mUseCustomDashPattern )
 
  253    mPen.setStyle( Qt::CustomDashLine );
 
  257    QVector<qreal> scaledVector;
 
  258    QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
 
  259    for ( ; it != mCustomDashVector.constEnd(); ++it )
 
  264    mPen.setDashPattern( scaledVector );
 
  268    mPen.setStyle( mPenStyle );
 
  271  if ( mDashPatternOffset && mPen.style() != Qt::SolidLine )
 
  276  mPen.setJoinStyle( mPenJoinStyle );
 
  277  mPen.setCapStyle( mPenCapStyle );
 
  282    selColor.setAlphaF( context.
opacity() );
 
  283  mSelPen.setColor( selColor );
 
 
  300  std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
 
  307  if ( mDrawInsidePolygon )
 
  315      if ( mDrawInsidePolygon )
 
  318        QPainterPath clipPath;
 
  319        clipPath.addPolygon( points );
 
  324          for ( 
auto it = rings->constBegin(); it != rings->constEnd(); ++it )
 
  326            QPolygonF ring = *it;
 
  327            clipPath.addPolygon( ring );
 
  332        p->setClipPath( clipPath, Qt::IntersectClip );
 
  355        for ( 
const QPolygonF &ring : std::as_const( *rings ) )
 
  371  if ( mDrawInsidePolygon )
 
 
  387  QPolygonF points = pts;
 
  389  double startTrim = mTrimDistanceStart;
 
  395  double endTrim = mTrimDistanceEnd;
 
  402  double totalLength = -1;
 
  406    startTrim = startTrim * 0.01 * totalLength;
 
  414    if ( totalLength < 0 ) 
 
  416    endTrim = endTrim * 0.01 * totalLength;
 
  429  mPen.setColor( penColor );
 
  432  applyDataDefinedSymbology( context, mPen, mSelPen, 
offset );
 
  435  const QPen pen = useSelectedColor ? mSelPen : mPen;
 
  437  if ( !pen.dashPattern().isEmpty() )
 
  440    const QVector<double> pattern = pen.dashPattern();
 
  441    bool foundNonNull = 
false;
 
  442    for ( 
int i = 0; i < pattern.size(); ++i )
 
  454  p->setBrush( Qt::NoBrush );
 
  457  std::unique_ptr< QgsScopedQPainterState > painterState;
 
  458  if ( points.size() <= 2 &&
 
  461       ( p->renderHints() & QPainter::Antialiasing ) )
 
  463    painterState = std::make_unique< QgsScopedQPainterState >( p );
 
  464    p->setRenderHint( QPainter::Antialiasing, 
false );
 
  467  const bool applyPatternTweaks = mAlignDashPattern
 
  468                                  && ( pen.style() != Qt::SolidLine || !pen.dashPattern().empty() )
 
  469                                  && pen.dashOffset() == 0;
 
  473    if ( applyPatternTweaks )
 
  475      drawPathWithDashPatternTweaks( p, points, pen );
 
  481      path.addPolygon( points );
 
  496    for ( 
const QPolygonF &part : mline )
 
  498      if ( applyPatternTweaks )
 
  500        drawPathWithDashPatternTweaks( p, part, pen );
 
  506        path.addPolygon( part );
 
 
  517  map[QStringLiteral( 
"line_width" )] = QString::number( 
mWidth );
 
  523  map[QStringLiteral( 
"offset" )] = QString::number( 
mOffset );
 
  526  map[QStringLiteral( 
"use_custom_dash" )] = ( mUseCustomDashPattern ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" ) );
 
  530  map[QStringLiteral( 
"dash_pattern_offset" )] = QString::number( mDashPatternOffset );
 
  533  map[QStringLiteral( 
"trim_distance_start" )] = QString::number( mTrimDistanceStart );
 
  536  map[QStringLiteral( 
"trim_distance_end" )] = QString::number( mTrimDistanceEnd );
 
  539  map[QStringLiteral( 
"draw_inside_polygon" )] = ( mDrawInsidePolygon ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" ) );
 
  540  map[QStringLiteral( 
"ring_filter" )] = QString::number( 
static_cast< int >( 
mRingFilter ) );
 
  541  map[QStringLiteral( 
"align_dash_pattern" )] = mAlignDashPattern ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" );
 
  542  map[QStringLiteral( 
"tweak_dash_pattern_on_corners" )] = mPatternCartographicTweakOnSharpCorners ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" );
 
 
  581  if ( mPenStyle == Qt::NoPen )
 
  584  QDomElement symbolizerElem = doc.createElement( QStringLiteral( 
"se:LineSymbolizer" ) );
 
  585  if ( !props.value( QStringLiteral( 
"uom" ), QString() ).toString().isEmpty() )
 
  586    symbolizerElem.setAttribute( QStringLiteral( 
"uom" ), props.value( QStringLiteral( 
"uom" ), QString() ).toString() );
 
  587  element.appendChild( symbolizerElem );
 
  593  QDomElement strokeElem = doc.createElement( QStringLiteral( 
"se:Stroke" ) );
 
  594  symbolizerElem.appendChild( strokeElem );
 
  596  Qt::PenStyle 
penStyle = mUseCustomDashPattern ? Qt::CustomDashLine : mPenStyle;
 
  605    QDomElement perpOffsetElem = doc.createElement( QStringLiteral( 
"se:PerpendicularOffset" ) );
 
  608    symbolizerElem.appendChild( perpOffsetElem );
 
 
  614  if ( mUseCustomDashPattern )
 
  617           mPen.color(), mPenJoinStyle,
 
  618           mPenCapStyle, 
mOffset, &mCustomDashVector );
 
 
  631  QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
  632  if ( strokeElem.isNull() )
 
  649  QDomElement perpOffsetElem = element.firstChildElement( QStringLiteral( 
"PerpendicularOffset" ) );
 
  650  if ( !perpOffsetElem.isNull() )
 
  653    double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
 
  658  double scaleFactor = 1.0;
 
  659  const QString uom = element.attribute( QStringLiteral( 
"uom" ) );
 
 
  674void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology( 
QgsSymbolRenderContext &context, QPen &pen, QPen &selPen, 
double &offset )
 
  680  bool hasStrokeWidthExpression = 
false;
 
  687    pen.setWidthF( scaledWidth );
 
  688    selPen.setWidthF( scaledWidth );
 
  689    hasStrokeWidthExpression = 
true;
 
  698    penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
 
  699    pen.setColor( penColor );
 
  713  const double dashWidthDiv = std::max( hasStrokeWidthExpression ? pen.widthF() : mPen.widthF(), 1.0 );
 
  717    QVector<qreal> dashVector;
 
  721      QStringList dashList = exprVal.toString().split( 
';' );
 
  722      QStringList::const_iterator dashIt = dashList.constBegin();
 
  723      for ( ; dashIt != dashList.constEnd(); ++dashIt )
 
  727      pen.setDashPattern( dashVector );
 
  734    QVector<qreal> scaledVector;
 
  735    for ( 
double v : std::as_const( mCustomDashVector ) )
 
  740    mPen.setDashPattern( scaledVector );
 
  744  double patternOffset = mDashPatternOffset;
 
  780void QgsSimpleLineSymbolLayer::drawPathWithDashPatternTweaks( QPainter *painter, 
const QPolygonF &points, QPen pen )
 const 
  782  if ( pen.dashPattern().empty() || points.size() < 2 )
 
  785  if ( pen.widthF() <= 1.0 )
 
  787    pen.setWidthF( 1.0001 );
 
  790  QVector< qreal > sourcePattern = pen.dashPattern();
 
  791  const double dashWidthDiv = pen.widthF();
 
  793  for ( 
int i = 0; i < sourcePattern.size(); ++ i )
 
  794    sourcePattern[i] *= pen.widthF();
 
  796  QVector< qreal > buffer;
 
  797  QPolygonF bufferedPoints;
 
  798  QPolygonF previousSegmentBuffer;
 
  803  auto ptIt = points.constBegin();
 
  804  double totalBufferLength = 0;
 
  805  int patternIndex = 0;
 
  806  double currentRemainingDashLength = 0;
 
  807  double currentRemainingGapLength = 0;
 
  809  auto compressPattern = []( 
const QVector< qreal > &buffer ) -> QVector< qreal >
 
  811    QVector< qreal > result;
 
  812    result.reserve( buffer.size() );
 
  813    for ( 
auto it = buffer.begin(); it != buffer.end(); )
 
  817      while ( dash == 0 && !result.empty() )
 
  819        result.last() += gap;
 
  821        if ( it == buffer.end() )
 
  826      while ( gap == 0 && it != buffer.end() )
 
  831      result << dash << gap;
 
  836  double currentBufferLineLength = 0;
 
  837  auto flushBuffer = [pen, painter, &buffer, &bufferedPoints, &previousSegmentBuffer, ¤tRemainingDashLength, ¤tRemainingGapLength,  ¤tBufferLineLength, &totalBufferLength,
 
  838                           dashWidthDiv, &compressPattern]( QPointF * nextPoint )
 
  840    if ( buffer.empty() || bufferedPoints.size() < 2 )
 
  845    if ( currentRemainingDashLength )
 
  848      buffer << currentRemainingDashLength << 0.0;
 
  849      totalBufferLength += currentRemainingDashLength;
 
  851    QVector< qreal > compressed = compressPattern( buffer );
 
  852    if ( !currentRemainingDashLength )
 
  855      totalBufferLength -= compressed.last();
 
  856      compressed.last() = 0;
 
  860    const double scaleFactor = currentBufferLineLength / totalBufferLength;
 
  862    bool shouldFlushPreviousSegmentBuffer = 
false;
 
  864    if ( !previousSegmentBuffer.empty() )
 
  868      if ( !firstDashSubstring.empty() )
 
  874      compressed = compressed.mid( 2 );
 
  875      shouldFlushPreviousSegmentBuffer = !compressed.empty();
 
  878    if ( !previousSegmentBuffer.empty() && ( shouldFlushPreviousSegmentBuffer || !nextPoint ) )
 
  880      QPen adjustedPen = pen;
 
  881      adjustedPen.setStyle( Qt::SolidLine );
 
  882      painter->setPen( adjustedPen );
 
  884      path.addPolygon( previousSegmentBuffer );
 
  885      painter->drawPath( path );
 
  886      previousSegmentBuffer.clear();
 
  889    double finalDash = 0;
 
  896      if ( !compressed.empty() )
 
  898        finalDash = compressed.at( compressed.size() - 2 );
 
  899        const double finalGap = compressed.size() > 2 ? compressed.at( compressed.size() - 3 ) : 0;
 
  901        const QPolygonF thisPoints = bufferedPoints;
 
  907        previousSegmentBuffer << bufferedPoints;
 
  911    currentBufferLineLength = 0;
 
  912    currentRemainingDashLength = 0;
 
  913    currentRemainingGapLength = 0;
 
  914    totalBufferLength = 0;
 
  917    if ( !bufferedPoints.empty() && ( !compressed.empty() || !nextPoint ) )
 
  919      QPen adjustedPen = pen;
 
  920      if ( !compressed.empty() )
 
  923        compressed = compressed.mid( 0, 32 );
 
  924        std::for_each( compressed.begin(), compressed.end(), [scaleFactor, dashWidthDiv]( qreal & element ) { element *= scaleFactor / dashWidthDiv; } );
 
  925        adjustedPen.setDashPattern( compressed );
 
  929        adjustedPen.setStyle( Qt::SolidLine );
 
  932      painter->setPen( adjustedPen );
 
  934      path.addPolygon( bufferedPoints );
 
  935      painter->drawPath( path );
 
  938    bufferedPoints.clear();
 
  944  bufferedPoints << p2;
 
  945  for ( ; ptIt != points.constEnd(); ++ptIt )
 
  953    double remainingSegmentDistance = std::sqrt( std::pow( p2.x() - p1.x(), 2.0 ) + std::pow( p2.y() - p1.y(), 2.0 ) );
 
  954    currentBufferLineLength += remainingSegmentDistance;
 
  958      if ( currentRemainingDashLength > 0 )
 
  961        if ( remainingSegmentDistance >= currentRemainingDashLength )
 
  964          buffer << currentRemainingDashLength << 0.0;
 
  965          totalBufferLength += currentRemainingDashLength;
 
  966          remainingSegmentDistance -= currentRemainingDashLength;
 
  968          currentRemainingDashLength = 0.0;
 
  969          currentRemainingGapLength = sourcePattern.at( patternIndex );
 
  970          if ( currentRemainingGapLength == 0.0 )
 
  978          buffer << remainingSegmentDistance << 0.0;
 
  979          totalBufferLength += remainingSegmentDistance;
 
  980          currentRemainingDashLength -= remainingSegmentDistance;
 
  984      if ( currentRemainingGapLength > 0 )
 
  987        if ( remainingSegmentDistance >= currentRemainingGapLength )
 
  990          buffer << 0.0 << currentRemainingGapLength;
 
  991          totalBufferLength += currentRemainingGapLength;
 
  992          remainingSegmentDistance -= currentRemainingGapLength;
 
  993          currentRemainingGapLength = 0.0;
 
  999          buffer << 0.0 << remainingSegmentDistance;
 
 1000          totalBufferLength += remainingSegmentDistance;
 
 1001          currentRemainingGapLength -= remainingSegmentDistance;
 
 1006      if ( patternIndex + 1 >= sourcePattern.size() )
 
 1011      const double nextPatternDashLength = sourcePattern.at( patternIndex );
 
 1012      const double nextPatternGapLength = sourcePattern.at( patternIndex + 1 );
 
 1013      if ( nextPatternDashLength + nextPatternGapLength <= remainingSegmentDistance )
 
 1015        buffer << nextPatternDashLength << nextPatternGapLength;
 
 1016        remainingSegmentDistance -= nextPatternDashLength + nextPatternGapLength;
 
 1017        totalBufferLength += nextPatternDashLength + nextPatternGapLength;
 
 1020      else if ( nextPatternDashLength <= remainingSegmentDistance )
 
 1023        buffer << nextPatternDashLength << remainingSegmentDistance - nextPatternDashLength;
 
 1024        totalBufferLength += remainingSegmentDistance;
 
 1025        currentRemainingGapLength = nextPatternGapLength - ( remainingSegmentDistance - nextPatternDashLength );
 
 1026        currentRemainingDashLength = 0;
 
 1033        buffer << remainingSegmentDistance << 0.0;
 
 1034        totalBufferLength += remainingSegmentDistance;
 
 1035        currentRemainingGapLength = 0;
 
 1036        currentRemainingDashLength = nextPatternDashLength - remainingSegmentDistance;
 
 1041    bufferedPoints << p1;
 
 1042    if ( mPatternCartographicTweakOnSharpCorners && ptIt + 1 != points.constEnd() )
 
 1044      QPointF nextPoint = *( ptIt + 1 );
 
 1050        flushBuffer( &nextPoint );
 
 1051        bufferedPoints << p1;
 
 1054        if ( patternIndex % 2 == 1 )
 
 1058        currentRemainingDashLength = sourcePattern.at( patternIndex );
 
 1065  flushBuffer( 
nullptr );
 
 1066  if ( !previousSegmentBuffer.empty() )
 
 1068    QPen adjustedPen = pen;
 
 1069    adjustedPen.setStyle( Qt::SolidLine );
 
 1070    painter->setPen( adjustedPen );
 
 1072    path.addPolygon( previousSegmentBuffer );
 
 1073    painter->drawPath( path );
 
 1074    previousSegmentBuffer.clear();
 
 1080  if ( mDrawInsidePolygon )
 
 
 1094  unit = mCustomDashPatternUnit;
 
 1095  return mUseCustomDashPattern ? mCustomDashVector : QVector<qreal>();
 
 
 1132  return mPenStyle != Qt::SolidLine || mUseCustomDashPattern;
 
 
 1137  return mAlignDashPattern;
 
 
 1147  return mPatternCartographicTweakOnSharpCorners;
 
 
 1152  mPatternCartographicTweakOnSharpCorners = 
enabled;
 
 
 1180    MyLine( QPointF p1, QPointF p2 )
 
 1181      : mVertical( false )
 
 1182      , mIncreasing( false )
 
 1194        mIncreasing = ( p2.y() > p1.y() );
 
 1199        mT = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
 
 1200        mIncreasing = ( p2.x() > p1.x() );
 
 1204      double x = ( p2.x() - p1.x() );
 
 1205      double y = ( p2.y() - p1.y() );
 
 1206      mLength = std::sqrt( x * x + y * y );
 
 1212      double a = ( mVertical ? M_PI_2 : std::atan( mT ) );
 
 1220    QPointF diffForInterval( 
double interval )
 
 1223        return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
 
 1225      double alpha = std::atan( mT );
 
 1226      double dx = std::cos( alpha ) * interval;
 
 1227      double dy = std::sin( alpha ) * interval;
 
 1228      return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
 
 1231    double length()
 const { 
return mLength; }
 
 1246  : mRotateSymbols( rotateSymbol )
 
 1247  , mInterval( interval )
 
 
 1286  if ( mRenderingFeature )
 
 1290    mFeatureSymbolOpacity = context.
opacity();
 
 1291    mCurrentFeatureIsSelected = useSelectedColor;
 
 1309      QString placementString = exprVal.toString();
 
 1310      if ( placementString.compare( QLatin1String( 
"interval" ), Qt::CaseInsensitive ) == 0 )
 
 1314      else if ( placementString.compare( QLatin1String( 
"vertex" ), Qt::CaseInsensitive ) == 0 )
 
 1318      else if ( placementString.compare( QLatin1String( 
"innervertices" ), Qt::CaseInsensitive ) == 0 )
 
 1322      else if ( placementString.compare( QLatin1String( 
"lastvertex" ), Qt::CaseInsensitive ) == 0 )
 
 1326      else if ( placementString.compare( QLatin1String( 
"firstvertex" ), Qt::CaseInsensitive ) == 0 )
 
 1330      else if ( placementString.compare( QLatin1String( 
"centerpoint" ), Qt::CaseInsensitive ) == 0 )
 
 1334      else if ( placementString.compare( QLatin1String( 
"curvepoint" ), Qt::CaseInsensitive ) == 0 )
 
 1338      else if ( placementString.compare( QLatin1String( 
"segmentcenter" ), Qt::CaseInsensitive ) == 0 )
 
 1351  double averageOver = mAverageAngleLength;
 
 1362      renderPolylineInterval( points, context, averageOver );
 
 1364      renderPolylineCentral( points, context, averageOver );
 
 1368         && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
 
 1371      mHasRenderedFirstPart = mRenderingFeature;
 
 1387    for ( 
int part = 0; part < mline.count(); ++part )
 
 1389      const QPolygonF &points2 = mline[ part ];
 
 1392        renderPolylineInterval( points2, context, averageOver );
 
 1394        renderPolylineCentral( points2, context, averageOver );
 
 1402           && ( mPlaceOnEveryPart || !mHasRenderedFirstPart ) )
 
 1405        mHasRenderedFirstPart = mRenderingFeature;
 
 
 1425  std::unique_ptr< QgsExpressionContextScopePopper > scopePopper;
 
 1455        for ( 
int i = 0; i < rings->size(); ++i )
 
 
 1488  mIntervalUnit = unit;
 
 1489  mOffsetAlongLineUnit = unit;
 
 1490  mAverageAngleLengthUnit = unit;
 
 
 1515  map[QStringLiteral( 
"rotate" )] = ( 
rotateSymbols() ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" ) );
 
 1516  map[QStringLiteral( 
"interval" )] = QString::number( 
interval() );
 
 1517  map[QStringLiteral( 
"offset" )] = QString::number( 
mOffset );
 
 1518  map[QStringLiteral( 
"offset_along_line" )] = QString::number( 
offsetAlongLine() );
 
 1525  map[QStringLiteral( 
"average_angle_length" )] = QString::number( mAverageAngleLength );
 
 1531  map[QStringLiteral( 
"ring_filter" )] = QString::number( 
static_cast< int >( 
mRingFilter ) );
 
 1532  map[QStringLiteral( 
"place_on_every_part" )] = mPlaceOnEveryPart;
 
 
 1538  return mPlaceOnEveryPart
 
 
 1548  mRenderingFeature = 
true;
 
 1549  mHasRenderedFirstPart = 
false;
 
 
 1554  mRenderingFeature = 
false;
 
 1565  renderSymbol( mFinalVertex, &feature, context, -1, mCurrentFeatureIsSelected );
 
 1566  mFeatureSymbolOpacity = 1;
 
 
 1595  if ( 
properties.contains( QStringLiteral( 
"offset" ) ) )
 
 1599  if ( 
properties.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 1603  if ( 
properties.contains( QStringLiteral( 
"interval_unit" ) ) )
 
 1607  if ( 
properties.contains( QStringLiteral( 
"offset_along_line" ) ) )
 
 1611  if ( 
properties.contains( QStringLiteral( 
"offset_along_line_unit" ) ) )
 
 1615  if ( 
properties.contains( ( QStringLiteral( 
"offset_along_line_map_unit_scale" ) ) ) )
 
 1620  if ( 
properties.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 1624  if ( 
properties.contains( QStringLiteral( 
"interval_map_unit_scale" ) ) )
 
 1629  if ( 
properties.contains( QStringLiteral( 
"average_angle_length" ) ) )
 
 1633  if ( 
properties.contains( QStringLiteral( 
"average_angle_unit" ) ) )
 
 1637  if ( 
properties.contains( ( QStringLiteral( 
"average_angle_map_unit_scale" ) ) ) )
 
 1642  if ( 
properties.contains( QStringLiteral( 
"placement" ) ) )
 
 1644    if ( 
properties[QStringLiteral( 
"placement" )] == QLatin1String( 
"vertex" ) )
 
 1646    else if ( 
properties[QStringLiteral( 
"placement" )] == QLatin1String( 
"lastvertex" ) )
 
 1648    else if ( 
properties[QStringLiteral( 
"placement" )] == QLatin1String( 
"firstvertex" ) )
 
 1650    else if ( 
properties[QStringLiteral( 
"placement" )] == QLatin1String( 
"centralpoint" ) )
 
 1652    else if ( 
properties[QStringLiteral( 
"placement" )] == QLatin1String( 
"curvepoint" ) )
 
 1654    else if ( 
properties[QStringLiteral( 
"placement" )] == QLatin1String( 
"segmentcenter" ) )
 
 1659  else if ( 
properties.contains( QStringLiteral( 
"placements" ) ) )
 
 1665  if ( 
properties.contains( QStringLiteral( 
"ring_filter" ) ) )
 
 
 1675void QgsTemplatedLineSymbolLayerBase::renderPolylineInterval( 
const QPolygonF &points, 
QgsSymbolRenderContext &context, 
double averageOver )
 
 1677  if ( points.isEmpty() )
 
 1681  double lengthLeft = 0; 
 
 1713  if ( painterUnitInterval < 0 )
 
 1716  double painterUnitOffsetAlongLine = 0;
 
 1719  double totalLength = -1;
 
 1740    if ( points.isClosed() )
 
 1742      if ( painterUnitOffsetAlongLine > 0 )
 
 1744        if ( totalLength < 0 )
 
 1746        painterUnitOffsetAlongLine = std::fmod( painterUnitOffsetAlongLine, totalLength );
 
 1748      else if ( painterUnitOffsetAlongLine < 0 )
 
 1750        if ( totalLength < 0 )
 
 1752        painterUnitOffsetAlongLine = totalLength - std::fmod( -painterUnitOffsetAlongLine, totalLength );
 
 1764  lengthLeft = painterUnitInterval - painterUnitOffsetAlongLine;
 
 1766  if ( averageOver > 0 && !
qgsDoubleNear( averageOver, 0.0 ) )
 
 1768    QVector< QPointF > angleStartPoints;
 
 1769    QVector< QPointF > symbolPoints;
 
 1770    QVector< QPointF > angleEndPoints;
 
 1778    collectOffsetPoints( points, symbolPoints, painterUnitInterval, lengthLeft );
 
 1780    if ( symbolPoints.empty() )
 
 1786    if ( symbolPoints.count() > 1 && symbolPoints.constFirst() == symbolPoints.constLast() )
 
 1789      symbolPoints.pop_back();
 
 1792    angleEndPoints.reserve( symbolPoints.size() );
 
 1793    angleStartPoints.reserve( symbolPoints.size() );
 
 1794    if ( averageOver <= painterUnitOffsetAlongLine )
 
 1796      collectOffsetPoints( points, angleStartPoints, painterUnitInterval, lengthLeft + averageOver, 0, symbolPoints.size() );
 
 1800      collectOffsetPoints( points, angleStartPoints, painterUnitInterval, 0, averageOver - painterUnitOffsetAlongLine, symbolPoints.size() );
 
 1802    collectOffsetPoints( points, angleEndPoints, painterUnitInterval, lengthLeft - averageOver, 0, symbolPoints.size() );
 
 1805    for ( 
int i = 0; i < symbolPoints.size(); ++ i )
 
 1810      const QPointF pt = symbolPoints[i];
 
 1811      const QPointF startPt = angleStartPoints[i];
 
 1812      const QPointF endPt = angleEndPoints[i];
 
 1814      MyLine l( startPt, endPt );
 
 1829    QPointF lastPt = points[0];
 
 1830    for ( 
int i = 1; i < points.count(); ++i )
 
 1835      const QPointF &pt = points[i];
 
 1841      MyLine l( lastPt, pt );
 
 1842      QPointF diff = l.diffForInterval( painterUnitInterval );
 
 1846      double c = 1 - lengthLeft / painterUnitInterval;
 
 1848      lengthLeft += l.length();
 
 1857      while ( lengthLeft > painterUnitInterval )
 
 1861        lengthLeft -= painterUnitInterval;
 
 1873static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
 
 1876  double a1 = MyLine( prevPt, pt ).angle();
 
 1877  double a2 = MyLine( pt, nextPt ).angle();
 
 1878  double unitX = std::cos( a1 ) + std::cos( a2 ), unitY = std::sin( a1 ) + std::sin( a2 );
 
 1880  return std::atan2( unitY, unitX );
 
 1885  if ( points.isEmpty() )
 
 1890  int i = -1, maxCount = 0;
 
 1891  bool isRing = 
false;
 
 1905  double totalLength = -1;
 
 1925    if ( points.isClosed() )
 
 1929        if ( totalLength < 0 )
 
 1935        if ( totalLength < 0 )
 
 2009      i = points.count() - 1;
 
 2011      maxCount = points.count();
 
 2019      maxCount = points.count() - 1;
 
 2027      maxCount = points.count();
 
 2028      if ( points.first() == points.last() )
 
 2045    renderOffsetVertexAlongLine( points, i, distance, context, 
placement );
 
 2052    prevPoint = points.at( 0 );
 
 2054  QPointF symbolPoint;
 
 2055  for ( ; i < maxCount; ++i )
 
 2066      QPointF currentPoint = points.at( i );
 
 2067      symbolPoint = QPointF( 0.5 * ( currentPoint.x() + prevPoint.x() ),
 
 2068                             0.5 * ( currentPoint.y() + prevPoint.y() ) );
 
 2071        double angle = std::atan2( currentPoint.y() - prevPoint.y(),
 
 2072                                   currentPoint.x() - prevPoint.x() );
 
 2075      prevPoint = currentPoint;
 
 2079      symbolPoint = points.at( i );
 
 2083        double angle = markerAngle( points, isRing, i );
 
 2088    mFinalVertex = symbolPoint;
 
 2094double QgsTemplatedLineSymbolLayerBase::markerAngle( 
const QPolygonF &points, 
bool isRing, 
int vertex )
 
 2097  const QPointF &pt = points[vertex];
 
 2099  if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
 
 2101    int prevIndex = vertex - 1;
 
 2102    int nextIndex = vertex + 1;
 
 2104    if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
 
 2106      prevIndex = points.count() - 2;
 
 2110    QPointF prevPoint, nextPoint;
 
 2111    while ( prevIndex >= 0 )
 
 2113      prevPoint = points[ prevIndex ];
 
 2114      if ( prevPoint != pt )
 
 2121    while ( nextIndex < points.count() )
 
 2123      nextPoint = points[ nextIndex ];
 
 2124      if ( nextPoint != pt )
 
 2131    if ( prevIndex >= 0 && nextIndex < points.count() )
 
 2133      angle = _averageAngle( prevPoint, pt, nextPoint );
 
 2140      while ( vertex < points.size() - 1 )
 
 2142        const QPointF &nextPt = points[vertex + 1];
 
 2145          angle = MyLine( pt, nextPt ).angle();
 
 2154      while ( vertex >= 1 ) 
 
 2156        const QPointF &prevPt = points[vertex - 1];
 
 2159          angle = MyLine( prevPt, pt ).angle();
 
 2171  if ( points.isEmpty() )
 
 2181      bool isRing = 
false;
 
 2182      if ( points.first() == points.last() )
 
 2184      double angle = markerAngle( points, isRing, vertex );
 
 2187    mFinalVertex = points[vertex];
 
 2193  int pointIncrement = distance > 0 ? 1 : -1;
 
 2194  QPointF previousPoint = points[vertex];
 
 2195  int startPoint = distance > 0 ? std::min( vertex + 1, 
static_cast<int>( points.count() ) - 1 ) : std::max( vertex - 1, 0 );
 
 2196  int endPoint = distance > 0 ? points.count() - 1 : 0;
 
 2197  double distanceLeft = std::fabs( distance );
 
 2199  for ( 
int i = startPoint; pointIncrement > 0 ? i <= endPoint : i >= endPoint; i += pointIncrement )
 
 2201    const QPointF &pt = points[i];
 
 2203    if ( previousPoint == pt ) 
 
 2207    MyLine l( previousPoint, pt );
 
 2209    if ( distanceLeft < l.length() )
 
 2212      QPointF markerPoint = previousPoint + l.diffForInterval( distanceLeft );
 
 2218      mFinalVertex = markerPoint;
 
 2224    distanceLeft -= l.length();
 
 2231void QgsTemplatedLineSymbolLayerBase::collectOffsetPoints( 
const QVector<QPointF> &p, QVector<QPointF> &dest, 
double intervalPainterUnits, 
double initialOffset, 
double initialLag, 
int numberPointsRequired )
 
 2236  QVector< QPointF > points = p;
 
 2237  const bool closedRing = points.first() == points.last();
 
 2239  double lengthLeft = initialOffset;
 
 2241  double initialLagLeft = initialLag > 0 ? -initialLag : 1; 
 
 2242  if ( initialLagLeft < 0 && closedRing )
 
 2245    QPointF lastPt = points.constLast();
 
 2246    QVector< QPointF > pseudoPoints;
 
 2247    for ( 
int i = points.count() - 2; i > 0; --i )
 
 2249      if ( initialLagLeft >= 0 )
 
 2254      const QPointF &pt = points[i];
 
 2259      MyLine l( lastPt, pt );
 
 2260      initialLagLeft += l.length();
 
 2265    std::reverse( pseudoPoints.begin(), pseudoPoints.end() );
 
 2267    points = pseudoPoints;
 
 2272    while ( initialLagLeft < 0 )
 
 2274      dest << points.constFirst();
 
 2275      initialLagLeft += intervalPainterUnits;
 
 2278  if ( initialLag > 0 )
 
 2280    lengthLeft += intervalPainterUnits - initialLagLeft;
 
 2283  QPointF lastPt = points[0];
 
 2284  for ( 
int i = 1; i < points.count(); ++i )
 
 2286    const QPointF &pt = points[i];
 
 2290      if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
 
 2299    MyLine l( lastPt, pt );
 
 2300    QPointF diff = l.diffForInterval( intervalPainterUnits );
 
 2304    double c = 1 - lengthLeft / intervalPainterUnits;
 
 2306    lengthLeft += l.length();
 
 2309    while ( lengthLeft > intervalPainterUnits || 
qgsDoubleNear( lengthLeft, intervalPainterUnits, 0.000000001 ) )
 
 2313      lengthLeft -= intervalPainterUnits;
 
 2316      if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
 
 2321    if ( numberPointsRequired > 0 && dest.size() >= numberPointsRequired )
 
 2325    if ( closedRing && i == points.count() - 1 && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
 
 2332  if ( !closedRing && numberPointsRequired > 0 && dest.size() < numberPointsRequired )
 
 2335    while ( dest.size() < numberPointsRequired )
 
 2336      dest << points.constLast();
 
 2340void QgsTemplatedLineSymbolLayerBase::renderPolylineCentral( 
const QPolygonF &points, 
QgsSymbolRenderContext &context, 
double averageAngleOver )
 
 2342  if ( !points.isEmpty() )
 
 2346    QPolygonF::const_iterator it = points.constBegin();
 
 2348    for ( ++it; it != points.constEnd(); ++it )
 
 2350      length += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
 
 2351                           ( last.y() - it->y() ) * ( last.y() - it->y() ) );
 
 2357    const double midPoint = length / 2;
 
 2360    double thisSymbolAngle = 0;
 
 2362    if ( averageAngleOver > 0 && !
qgsDoubleNear( averageAngleOver, 0.0 ) )
 
 2364      QVector< QPointF > angleStartPoints;
 
 2365      QVector< QPointF > symbolPoints;
 
 2366      QVector< QPointF > angleEndPoints;
 
 2368      collectOffsetPoints( points, symbolPoints, midPoint, midPoint, 0.0, 2 );
 
 2369      collectOffsetPoints( points, angleStartPoints, midPoint, 0, averageAngleOver, 2 );
 
 2370      collectOffsetPoints( points, angleEndPoints, midPoint, midPoint - averageAngleOver, 0, 2 );
 
 2372      pt = symbolPoints.at( 1 );
 
 2373      MyLine l( angleStartPoints.at( 1 ), angleEndPoints.at( 1 ) );
 
 2374      thisSymbolAngle = l.angle();
 
 2379      it = points.constBegin();
 
 2381      qreal last_at = 0, next_at = 0;
 
 2383      for ( ++it; it != points.constEnd(); ++it )
 
 2386        next_at += std::sqrt( ( last.x() - it->x() ) * ( last.x() - it->x() ) +
 
 2387                              ( last.y() - it->y() ) * ( last.y() - it->y() ) );
 
 2388        if ( next_at >= midPoint )
 
 2395      MyLine l( last, next ); 
 
 2396      qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
 
 2397      pt = last + ( next - last ) * k;
 
 2398      thisSymbolAngle = l.angle();
 
 2450  if ( props.contains( QStringLiteral( 
"interval" ) ) )
 
 2451    interval = props[QStringLiteral( 
"interval" )].toDouble();
 
 2452  if ( props.contains( QStringLiteral( 
"rotate" ) ) )
 
 2453    rotate = ( props[QStringLiteral( 
"rotate" )].toString() == QLatin1String( 
"1" ) );
 
 2455  auto x = std::make_unique< QgsMarkerLineSymbolLayer >( rotate, 
interval );
 
 
 2462  return QStringLiteral( 
"MarkerLine" );
 
 
 2482  mMarker->setRenderHints( hints );
 
 
 2502  for ( 
int i = 0; i < 
mMarker->symbolLayerCount(); i++ )
 
 2504    QDomElement symbolizerElem = doc.createElement( QStringLiteral( 
"se:LineSymbolizer" ) );
 
 2505    if ( !props.value( QStringLiteral( 
"uom" ), QString() ).toString().isEmpty() )
 
 2506      symbolizerElem.setAttribute( QStringLiteral( 
"uom" ), props.value( QStringLiteral( 
"uom" ), QString() ).toString() );
 
 2507    element.appendChild( symbolizerElem );
 
 2537    QDomElement strokeElem = doc.createElement( QStringLiteral( 
"se:Stroke" ) );
 
 2538    symbolizerElem.appendChild( strokeElem );
 
 2541    QDomElement graphicStrokeElem = doc.createElement( QStringLiteral( 
"se:GraphicStroke" ) );
 
 2542    strokeElem.appendChild( graphicStrokeElem );
 
 2547      markerLayer->writeSldMarker( doc, graphicStrokeElem, props );
 
 2551      graphicStrokeElem.appendChild( doc.createComment( QStringLiteral( 
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() ) ) );
 
 2555      graphicStrokeElem.appendChild( doc.createComment( QStringLiteral( 
"Missing marker line symbol layer. Skip it." ) ) );
 
 2558    if ( !gap.isEmpty() )
 
 2560      QDomElement gapElem = doc.createElement( QStringLiteral( 
"se:Gap" ) );
 
 2562      graphicStrokeElem.appendChild( gapElem );
 
 2567      QDomElement perpOffsetElem = doc.createElement( QStringLiteral( 
"se:PerpendicularOffset" ) );
 
 2570      symbolizerElem.appendChild( perpOffsetElem );
 
 
 2579  QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 2580  if ( strokeElem.isNull() )
 
 2583  QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral( 
"GraphicStroke" ) );
 
 2584  if ( graphicStrokeElem.isNull() )
 
 2592  for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
 
 2594    if ( it.key() == QLatin1String( 
"placement" ) )
 
 2596      if ( it.value() == QLatin1String( 
"points" ) )
 
 2598      else if ( it.value() == QLatin1String( 
"firstPoint" ) )
 
 2600      else if ( it.value() == QLatin1String( 
"lastPoint" ) )
 
 2602      else if ( it.value() == QLatin1String( 
"centralPoint" ) )
 
 2605    else if ( it.value() == QLatin1String( 
"rotateMarker" ) )
 
 2611  std::unique_ptr< QgsMarkerSymbol > marker;
 
 2625  QDomElement gapElem = graphicStrokeElem.firstChildElement( QStringLiteral( 
"Gap" ) );
 
 2626  if ( !gapElem.isNull() )
 
 2629    double d = gapElem.firstChild().nodeValue().toDouble( &ok );
 
 2635  QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement( QStringLiteral( 
"PerpendicularOffset" ) );
 
 2636  if ( !perpOffsetElem.isNull() )
 
 2639    double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
 
 2644  double scaleFactor = 1.0;
 
 2645  const QString uom = element.attribute( QStringLiteral( 
"uom" ) );
 
 
 2668    mMarker->setDataDefinedSize( property );
 
 
 2675  const double prevOpacity = 
mMarker->opacity();
 
 2678  mMarker->setOpacity( prevOpacity );
 
 
 2683  mMarker->setLineAngle( angle );
 
 
 2701  mMarker->renderPoint( point, feature, context, layer, selected );
 
 
 2713  return mMarker->size( context );
 
 
 2719  mMarker->setOutputUnit( unit );
 
 
 2736    attr.unite( 
mMarker->usedAttributes( context ) );
 
 
 2751  return ( 
mMarker->size( context ) / 2.0 ) +
 
 
 2773  if ( props.contains( QStringLiteral( 
"interval" ) ) )
 
 2774    interval = props[QStringLiteral( 
"interval" )].toDouble();
 
 2775  if ( props.contains( QStringLiteral( 
"rotate" ) ) )
 
 2776    rotate = ( props[QStringLiteral( 
"rotate" )] == QLatin1String( 
"1" ) );
 
 2778  auto x = std::make_unique< QgsHashedLineSymbolLayer >( rotate, 
interval );
 
 2780  if ( props.contains( QStringLiteral( 
"hash_angle" ) ) )
 
 2782    x->setHashAngle( props[QStringLiteral( 
"hash_angle" )].toDouble() );
 
 2785  if ( props.contains( QStringLiteral( 
"hash_length" ) ) )
 
 2786    x->setHashLength( props[QStringLiteral( 
"hash_length" )].toDouble() );
 
 2788  if ( props.contains( QStringLiteral( 
"hash_length_unit" ) ) )
 
 2791  if ( props.contains( QStringLiteral( 
"hash_length_map_unit_scale" ) ) )
 
 
 2799  return QStringLiteral( 
"HashLine" );
 
 
 2808  mHashSymbol->setRenderHints( hints );
 
 
 2821  map[ QStringLiteral( 
"hash_angle" ) ] = QString::number( mHashAngle );
 
 2823  map[QStringLiteral( 
"hash_length" )] = QString::number( mHashLength );
 
 
 2834  x->setHashAngle( mHashAngle );
 
 2835  x->setHashLength( mHashLength );
 
 2836  x->setHashLengthUnit( mHashLengthUnit );
 
 2837  x->setHashLengthMapUnitScale( mHashLengthMapUnitScale );
 
 
 2843  mHashSymbol->setColor( 
color );
 
 
 2849  return mHashSymbol ? mHashSymbol->color() : 
mColor;
 
 
 2854  return mHashSymbol.get();
 
 
 2865  mHashSymbol.reset( 
static_cast<QgsLineSymbol *
>( symbol ) );
 
 2866  mColor = mHashSymbol->color();
 
 
 2872  mHashLength = 
width;
 
 
 2887  return ( mHashSymbol->width( context ) / 2.0 )
 
 
 2895  mHashSymbol->setOutputUnit( unit );
 
 
 2902    attr.unite( mHashSymbol->usedAttributes( context ) );
 
 
 2910  if ( mHashSymbol && mHashSymbol->hasDataDefinedProperties() )
 
 
 2919    mHashSymbol->setDataDefinedWidth( property );
 
 
 2932         || ( mHashSymbol && mHashSymbol->usesMapUnits() );
 
 
 2937  mSymbolLineAngle = angle;
 
 
 2942  return mSymbolAngle;
 
 
 2947  mSymbolAngle = angle;
 
 
 2952  double lineLength = mHashLength;
 
 2958  const double w = context.
convertToPainterUnits( lineLength, mHashLengthUnit, mHashLengthMapUnitScale ) / 2.0;
 
 2972  points <<  QPointF( start.
x(), start.
y() ) << QPointF( end.
x(), end.
y() );
 
 2977  mHashSymbol->renderPolyline( points, feature, context, layer, selected );
 
 
 2994  const double prevOpacity = mHashSymbol->opacity();
 
 2995  mHashSymbol->setOpacity( mHashSymbol->opacity() * context.
opacity() );
 
 2997  mHashSymbol->setOpacity( prevOpacity );
 
 
 3016  QPolygonF offsetPoints;
 
 3019    renderLine( points, context, patternThickness, patternLength, brush );
 
 3028      renderLine( part, context, patternThickness, patternLength, brush );
 
 
 3033void QgsAbstractBrushedLineSymbolLayer::renderLine( 
const QPolygonF &points, 
QgsSymbolRenderContext &context, 
const double lineThickness,
 
 3034    const double patternLength, 
const QBrush &sourceBrush )
 
 3040  QBrush brush = sourceBrush;
 
 3045  QPolygonF inputPoints;
 
 3046  inputPoints.reserve( points.size() );
 
 3048  double minX = std::numeric_limits< double >::max();
 
 3049  double minY = std::numeric_limits< double >::max();
 
 3050  double maxX = std::numeric_limits< double >::lowest();
 
 3051  double maxY = std::numeric_limits< double >::lowest();
 
 3053  for ( 
const QPointF &pt : std::as_const( points ) )
 
 3060    minX = std::min( minX, pt.x() );
 
 3061    minY = std::min( minY, pt.y() );
 
 3062    maxX = std::max( maxX, pt.x() );
 
 3063    maxY = std::max( maxY, pt.y() );
 
 3066  if ( inputPoints.size() < 2 ) 
 
 3070  constexpr int ANTIALIAS_ALLOWANCE_PIXELS = 10;
 
 3072  constexpr double ANTIALIAS_OVERLAP_PIXELS = 0.5;
 
 3075  const int imageWidth = 
static_cast< int >( std::ceil( maxX - minX ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
 
 3076  const int imageHeight = 
static_cast< int >( std::ceil( maxY - minY ) + lineThickness * 2 ) + ANTIALIAS_ALLOWANCE_PIXELS * 2;
 
 3078  const bool isClosedLine = 
qgsDoubleNear( points.at( 0 ).x(), points.constLast().x(), 0.01 )
 
 3079                            && 
qgsDoubleNear( points.at( 0 ).y(), points.constLast().y(), 0.01 );
 
 3081  QImage temporaryImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
 
 3082  if ( temporaryImage.isNull() )
 
 3091  temporaryImage.fill( Qt::transparent );
 
 3114  QPainterPathStroker stroker;
 
 3115  stroker.setWidth( lineThickness );
 
 3116  stroker.setCapStyle( cap );
 
 3117  stroker.setJoinStyle( join );
 
 3120  path.addPolygon( inputPoints );
 
 3121  const QPainterPath stroke = stroker.createStroke( path ).simplified();
 
 3124  QPainter imagePainter;
 
 3125  imagePainter.begin( &temporaryImage );
 
 3127  imagePainter.translate( -minX + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS, -minY + lineThickness + ANTIALIAS_ALLOWANCE_PIXELS );
 
 3129  imagePainter.setClipPath( stroke, Qt::IntersectClip );
 
 3130  imagePainter.setPen( Qt::NoPen );
 
 3132  QPointF segmentStartPoint = inputPoints.at( 0 );
 
 3135  double progressThroughImage = 0;
 
 3137  QgsPoint prevSegmentPolygonEndLeft;
 
 3138  QgsPoint prevSegmentPolygonEndRight;
 
 3144  for ( 
int i = 1; i < inputPoints.size(); ++i )
 
 3149    const QPointF segmentEndPoint = inputPoints.at( i );
 
 3151                                       segmentEndPoint.x(), segmentEndPoint.y() ) - 90;
 
 3154    QgsPoint thisSegmentPolygonEndLeft;
 
 3155    QgsPoint thisSegmentPolygonEndRight;
 
 3157    QgsPoint thisSegmentPolygonEndLeftForPainter;
 
 3158    QgsPoint thisSegmentPolygonEndRightForPainter;
 
 3166        const QgsPoint startPointLeft = 
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
 
 3168        const QgsPoint startPointRight = 
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
 
 3169        const QgsPoint endPointRight = 
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
 
 3173        const double lastSegmentAngleDegrees = 180.0 / M_PI * 
QgsGeometryUtilsBase::lineAngle( points.at( points.size() - 2 ).x(), points.at( points.size() - 2 ).y(),
 
 3174                                               segmentStartPoint.x(), segmentStartPoint.y() ) - 90;
 
 3177        const QgsPoint lastSegmentStartPointLeft = 
QgsPoint( points.at( points.size() - 2 ) ).
project( lineThickness / 2, lastSegmentAngleDegrees );
 
 3178        const QgsPoint lastSegmentEndPointLeft = 
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, lastSegmentAngleDegrees );
 
 3179        const QgsPoint lastSegmentStartPointRight = 
QgsPoint( points.at( points.size() - 2 ) ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
 
 3180        const QgsPoint lastSegmentEndPointRight = 
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, lastSegmentAngleDegrees );
 
 3186        bool isIntersection = 
false;
 
 3188        if ( !isIntersection )
 
 3189          prevSegmentPolygonEndLeft = startPointLeft;
 
 3190        isIntersection = 
false;
 
 3191        QgsGeometryUtils::segmentIntersection( lastSegmentStartPointRight, lastSegmentEndPointRight, startPointRight, endPointRight, prevSegmentPolygonEndRight, isIntersection, 1e-8, 
true );
 
 3192        if ( !isIntersection )
 
 3193          prevSegmentPolygonEndRight = startPointRight;
 
 3195        startLinePolygonLeft = prevSegmentPolygonEndLeft;
 
 3196        startLinePolygonRight = prevSegmentPolygonEndRight;
 
 3200        prevSegmentPolygonEndLeft = 
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
 
 3201        if ( cap != Qt::PenCapStyle::FlatCap )
 
 3202          prevSegmentPolygonEndLeft = prevSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees - 90 );
 
 3203        prevSegmentPolygonEndRight = 
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
 
 3204        if ( cap != Qt::PenCapStyle::FlatCap )
 
 3205          prevSegmentPolygonEndRight = prevSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees - 90 );
 
 3209    if ( i < inputPoints.size() - 1 )
 
 3214      const QgsPoint startPointLeft = 
QgsPoint( segmentStartPoint ).
project( lineThickness / 2, segmentAngleDegrees );
 
 3216      const QgsPoint startPointRight = 
QgsPoint( segmentStartPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
 
 3217      const QgsPoint endPointRight = 
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
 
 3222                                             inputPoints.at( i + 1 ).x(), inputPoints.at( i + 1 ).y() ) - 90;
 
 3225      const QgsPoint nextSegmentStartPointLeft = 
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, nextSegmentAngleDegrees );
 
 3226      const QgsPoint nextSegmentEndPointLeft = 
QgsPoint( inputPoints.at( i + 1 ) ).
project( lineThickness / 2, nextSegmentAngleDegrees );
 
 3227      const QgsPoint nextSegmentStartPointRight = 
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
 
 3228      const QgsPoint nextSegmentEndPointRight = 
QgsPoint( inputPoints.at( i + 1 ) ).
project( -lineThickness / 2, nextSegmentAngleDegrees );
 
 3234      bool isIntersection = 
false;
 
 3236      if ( !isIntersection )
 
 3237        thisSegmentPolygonEndLeft = endPointLeft;
 
 3238      isIntersection = 
false;
 
 3239      QgsGeometryUtils::segmentIntersection( startPointRight, endPointRight, nextSegmentStartPointRight, nextSegmentEndPointRight, thisSegmentPolygonEndRight, isIntersection, 1e-8, 
true );
 
 3240      if ( !isIntersection )
 
 3241        thisSegmentPolygonEndRight = endPointRight;
 
 3243      thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
 
 3244      thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
 
 3252        thisSegmentPolygonEndLeft = startLinePolygonLeft;
 
 3253        thisSegmentPolygonEndRight = startLinePolygonRight;
 
 3255        thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
 
 3256        thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight.
project( ANTIALIAS_OVERLAP_PIXELS, segmentAngleDegrees + 90 );
 
 3260        thisSegmentPolygonEndLeft = 
QgsPoint( segmentEndPoint ).
project( lineThickness / 2, segmentAngleDegrees );
 
 3261        if ( cap != Qt::PenCapStyle::FlatCap )
 
 3262          thisSegmentPolygonEndLeft = thisSegmentPolygonEndLeft.
project( lineThickness / 2, segmentAngleDegrees + 90 );
 
 3263        thisSegmentPolygonEndRight = 
QgsPoint( segmentEndPoint ).
project( -lineThickness / 2, segmentAngleDegrees );
 
 3264        if ( cap != Qt::PenCapStyle::FlatCap )
 
 3265          thisSegmentPolygonEndRight = thisSegmentPolygonEndRight.
project( lineThickness / 2, segmentAngleDegrees + 90 );
 
 3267        thisSegmentPolygonEndLeftForPainter = thisSegmentPolygonEndLeft;
 
 3268        thisSegmentPolygonEndRightForPainter = thisSegmentPolygonEndRight;
 
 3274    QTransform brushTransform;
 
 3275    brushTransform.translate( segmentStartPoint.x(), segmentStartPoint.y() );
 
 3276    brushTransform.rotate( -segmentAngleDegrees );
 
 3277    if ( i == 1 && cap != Qt::PenCapStyle::FlatCap )
 
 3281      brushTransform.translate( -( lineThickness / 2 ), 0 );
 
 3283    brushTransform.translate( -progressThroughImage, -lineThickness / 2 );
 
 3285    brush.setTransform( brushTransform );
 
 3286    imagePainter.setBrush( brush );
 
 3289    imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
 
 3290                              << thisSegmentPolygonEndLeftForPainter.
toQPointF()
 
 3291                              << thisSegmentPolygonEndRightForPainter.
toQPointF()
 
 3292                              << prevSegmentPolygonEndRight.
toQPointF()
 
 3293                              << prevSegmentPolygonEndLeft.
toQPointF() );
 
 3296    imagePainter.setPen( QPen( QColor( 0, 255, 255 ), 2 ) );
 
 3297    imagePainter.setBrush( Qt::NoBrush );
 
 3298    imagePainter.drawPolygon( QPolygonF() << prevSegmentPolygonEndLeft.
toQPointF()
 
 3299                              << thisSegmentPolygonEndLeftForPainter.
toQPointF()
 
 3300                              << thisSegmentPolygonEndRightForPainter.
toQPointF()
 
 3301                              << prevSegmentPolygonEndRight.
toQPointF()
 
 3302                              << prevSegmentPolygonEndLeft.
toQPointF() );
 
 3303    imagePainter.setPen( Qt::NoPen );
 
 3308    progressThroughImage += sqrt( std::pow( segmentStartPoint.x() - segmentEndPoint.x(), 2 )
 
 3309                                  +  std::pow( segmentStartPoint.y() - segmentEndPoint.y(), 2 ) )
 
 3310                            + ( i == 1 && cap != Qt::PenCapStyle::FlatCap ? lineThickness / 2 : 0 ); 
 
 3311    progressThroughImage = fmod( progressThroughImage, patternLength );
 
 3314    segmentStartPoint = segmentEndPoint;
 
 3315    prevSegmentPolygonEndLeft = thisSegmentPolygonEndLeft;
 
 3316    prevSegmentPolygonEndRight = thisSegmentPolygonEndRight;
 
 3324  p->drawImage( QPointF( minX - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS,
 
 3325                         minY - lineThickness - ANTIALIAS_ALLOWANCE_PIXELS ), temporaryImage );
 
 3342  auto res = std::make_unique<QgsRasterLineSymbolLayer>();
 
 3344  if ( 
properties.contains( QStringLiteral( 
"line_width" ) ) )
 
 3346    res->setWidth( 
properties[QStringLiteral( 
"line_width" )].toDouble() );
 
 3348  if ( 
properties.contains( QStringLiteral( 
"line_width_unit" ) ) )
 
 3352  if ( 
properties.contains( QStringLiteral( 
"width_map_unit_scale" ) ) )
 
 3357  if ( 
properties.contains( QStringLiteral( 
"imageFile" ) ) )
 
 3358    res->setPath( 
properties[QStringLiteral( 
"imageFile" )].toString() );
 
 3360  if ( 
properties.contains( QStringLiteral( 
"offset" ) ) )
 
 3362    res->setOffset( 
properties[QStringLiteral( 
"offset" )].toDouble() );
 
 3364  if ( 
properties.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 3368  if ( 
properties.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 3373  if ( 
properties.contains( QStringLiteral( 
"joinstyle" ) ) )
 
 3375  if ( 
properties.contains( QStringLiteral( 
"capstyle" ) ) )
 
 3378  if ( 
properties.contains( QStringLiteral( 
"alpha" ) ) )
 
 3380    res->setOpacity( 
properties[QStringLiteral( 
"alpha" )].toDouble() );
 
 3383  return res.release();
 
 
 3390  map[QStringLiteral( 
"imageFile" )] = 
mPath;
 
 3392  map[QStringLiteral( 
"line_width" )] = QString::number( 
mWidth );
 
 3399  map[QStringLiteral( 
"offset" )] = QString::number( 
mOffset );
 
 3403  map[QStringLiteral( 
"alpha" )] = QString::number( 
mOpacity );
 
 
 3410  auto res = std::make_unique< QgsRasterLineSymbolLayer >( 
mPath );
 
 3422  return res.release();
 
 
 3427  const QVariantMap::iterator it = 
properties.find( QStringLiteral( 
"imageFile" ) );
 
 3428  if ( it != 
properties.end() && it.value().userType() == QMetaType::Type::QString )
 
 
 3444  return QStringLiteral( 
"RasterLine" );
 
 
 3459  bool cached = 
false;
 
 3461               QSize( 
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
 
 3462                      static_cast< int >( std::ceil( scaledHeight ) ) ),
 
 
 3487    double strokeWidth = 
mWidth;
 
 3504    bool cached = 
false;
 
 3506                  QSize( 
static_cast< int >( std::round( originalSize.width() / originalSize.height() * std::max( 1.0, scaledHeight ) ) ),
 
 3507                         static_cast< int >( std::ceil( scaledHeight ) ) ),
 
 3512  if ( useSelectedColor )
 
 3517  const QBrush brush( sourceImage );
 
 
 3587  auto res = std::make_unique<QgsLineburstSymbolLayer>();
 
 3589  if ( 
properties.contains( QStringLiteral( 
"line_width" ) ) )
 
 3591    res->setWidth( 
properties[QStringLiteral( 
"line_width" )].toDouble() );
 
 3593  if ( 
properties.contains( QStringLiteral( 
"line_width_unit" ) ) )
 
 3597  if ( 
properties.contains( QStringLiteral( 
"width_map_unit_scale" ) ) )
 
 3602  if ( 
properties.contains( QStringLiteral( 
"offset" ) ) )
 
 3604    res->setOffset( 
properties[QStringLiteral( 
"offset" )].toDouble() );
 
 3606  if ( 
properties.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 3610  if ( 
properties.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 3615  if ( 
properties.contains( QStringLiteral( 
"joinstyle" ) ) )
 
 3617  if ( 
properties.contains( QStringLiteral( 
"capstyle" ) ) )
 
 3620  if ( 
properties.contains( QStringLiteral( 
"color_type" ) ) )
 
 3623  if ( 
properties.contains( QStringLiteral( 
"color" ) ) )
 
 3627  if ( 
properties.contains( QStringLiteral( 
"gradient_color2" ) ) )
 
 3642  return res.release();
 
 
 3649  map[QStringLiteral( 
"line_width" )] = QString::number( 
mWidth );
 
 3656  map[QStringLiteral( 
"offset" )] = QString::number( 
mOffset );
 
 3662  map[QStringLiteral( 
"color_type" )] = QString::number( 
static_cast< int >( 
mGradientColorType ) );
 
 
 3673  auto res = std::make_unique< QgsLineburstSymbolLayer >();
 
 3689  return res.release();
 
 
 3694  return QStringLiteral( 
"Lineburst" );
 
 
 3715  double strokeWidth = 
mWidth;
 
 3731  if ( useSelectedColor )
 
 3735  color1.setAlphaF( context.
opacity() * color1.alphaF() );
 
 3746  QGradient gradient = QLinearGradient( QPointF( 0, 0 ), QPointF( 0, scaledWidth ) );
 
 3758    gradient.setColorAt( 0.0, color1 );
 
 3759    gradient.setColorAt( 1.0, 
color2 );
 
 3761  const QBrush brush( gradient );
 
 
 3840  if ( props.contains( QStringLiteral( 
"line_width" ) ) )
 
 3842    width = props[QStringLiteral( 
"line_width" )].toDouble();
 
 3844  else if ( props.contains( QStringLiteral( 
"outline_width" ) ) )
 
 3846    width = props[QStringLiteral( 
"outline_width" )].toDouble();
 
 3848  else if ( props.contains( QStringLiteral( 
"width" ) ) )
 
 3850    width = props[QStringLiteral( 
"width" )].toDouble();
 
 3855  if ( props.contains( QStringLiteral( 
"line_width_unit" ) ) )
 
 3859  else if ( props.contains( QStringLiteral( 
"outline_width_unit" ) ) )
 
 3863  else if ( props.contains( QStringLiteral( 
"width_unit" ) ) )
 
 3868  if ( props.contains( QStringLiteral( 
"width_map_unit_scale" ) ) )
 
 3870  if ( props.contains( QStringLiteral( 
"offset" ) ) )
 
 3871    l->setOffset( props[QStringLiteral( 
"offset" )].toDouble() );
 
 3872  if ( props.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 3874  if ( props.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 3876  if ( props.contains( QStringLiteral( 
"joinstyle" ) ) )
 
 3878  if ( props.contains( QStringLiteral( 
"capstyle" ) ) )
 
 3881  l->restoreOldDataDefinedProperties( props );
 
 
 3888  return QStringLiteral( 
"FilledLine" );
 
 
 3937  Qt::PenJoinStyle join = mPenJoinStyle;
 
 3946  Qt::PenCapStyle cap = mPenCapStyle;
 
 3962  const double prevOpacity = mFill->opacity();
 
 3963  mFill->setOpacity( mFill->opacity() * context.
opacity() );
 
 3970  if ( points.count() >= 2 )
 
 3973    geos::unique_ptr lineGeom;
 
 3988        auto inputPoly = std::make_unique< QgsPolygon >( 
static_cast< QgsLineString * 
>( ls.release() ) );
 
 3994        if ( !parts.empty() )
 
 4016      geos::unique_ptr buffered = 
QgsGeos::buffer( lineGeom.get(), scaledWidth / 2, 8,
 
 4022        std::unique_ptr< QgsAbstractGeometry > bufferedGeom = 
QgsGeos::fromGeos( buffered.get() );
 
 4024        for ( 
const QList< QPolygonF > &polygon : parts )
 
 4026          QVector< QPolygonF > rings;
 
 4027          for ( 
int i = 1; i < polygon.size(); ++i )
 
 4028            rings << polygon.at( i );
 
 4029          mFill->renderPolygon( polygon.value( 0 ), &rings, context.
feature(), context.
renderContext(), -1, useSelectedColor );
 
 4037  mFill->setOpacity( prevOpacity );
 
 
 4044  map[QStringLiteral( 
"line_width" )] = QString::number( 
mWidth );
 
 4049  map[QStringLiteral( 
"offset" )] = QString::number( 
mOffset );
 
 
 4064  res->setSubSymbol( mFill->clone() );
 
 4065  return res.release();
 
 
 4100    attr.unite( mFill->usedAttributes( context ) );
 
 
 4108  if ( mFill && mFill->hasDataDefinedProperties() )
 
 
 4117    mFill->setColor( 
c );
 
 
 4122  return mFill ? mFill->color() : 
mColor;
 
 
 4129         || ( mFill && mFill->usesMapUnits() );
 
 
 4136    mFill->setMapUnitScale( scale );
 
 
 4143    return mFill->mapUnitScale();
 
 
 4152    mFill->setOutputUnit( unit );
 
 
 4159    return mFill->outputUnit();
 
 
MarkerLinePlacement
Defines how/where the symbols should be placed on a line.
 
@ CurvePoint
Place symbols at every virtual curve point in the line (used when rendering curved geometry types onl...
 
@ InnerVertices
Inner vertices (i.e. all vertices except the first and last vertex)
 
@ LastVertex
Place symbols on the last vertex in the line.
 
@ CentralPoint
Place symbols at the mid point of the line.
 
@ SegmentCenter
Place symbols at the center of every line segment.
 
@ Vertex
Place symbols on every vertex in the line.
 
@ Interval
Place symbols at regular intervals.
 
@ FirstVertex
Place symbols on the first vertex in the line.
 
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
 
@ IsSymbolLayerSubSymbol
Symbol is being rendered as a sub-symbol of a QgsSymbolLayer.
 
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
 
GradientColorSource
Gradient color sources.
 
@ ColorRamp
Gradient color ramp.
 
@ CanCalculateMaskGeometryPerFeature
If present, indicates that mask geometry can safely be calculated per feature for the symbol layer....
 
@ Curve
An intermediate point on a segment defining the curvature of the segment.
 
@ Segment
The actual start or end point of a segment.
 
QFlags< SymbolLayerFlag > SymbolLayerFlags
Symbol layer flags.
 
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
 
@ Miter
Use mitered joins.
 
RenderUnit
Rendering size units.
 
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
 
@ Millimeters
Millimeters.
 
@ Points
Points (e.g., for font sizes)
 
@ Unknown
Mixed or unknown units.
 
@ MetersInMapUnits
Meters value as Map units.
 
@ Flat
Flat cap (in line with start/end of line)
 
@ RenderingSubSymbol
Set whenever a sub-symbol of a parent symbol is currently being rendered. Can be used during symbol a...
 
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
 
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
 
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
 
@ MultiLineString
MultiLineString.
 
QFlags< MarkerLinePlacement > MarkerLinePlacements
 
Base class for line symbol layer types which draws line sections using a QBrush.
 
Qt::PenCapStyle mPenCapStyle
 
Qt::PenJoinStyle mPenJoinStyle
 
void renderPolylineUsingBrush(const QPolygonF &points, QgsSymbolRenderContext &context, const QBrush &brush, double patternThickness, double patternLength)
Renders a polyline of points using the specified brush.
 
static bool isGeneralizableByDeviceBoundingBox(const QgsRectangle &envelope, float mapToPixelTol=1.0f)
Returns whether the device-envelope can be replaced by its BBOX when is applied the specified toleran...
 
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
 
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
 
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
 
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
 
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
 
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
 
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
 
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
 
Abstract base class for color ramps.
 
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
 
static QString colorToString(const QColor &color)
Encodes a color into a string value.
 
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
 
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
 
Curve polygon geometry type.
 
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
 
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
 
Exports QGIS layers to the DXF format.
 
static double mapUnitScaleFactor(double scale, Qgis::RenderUnit symbolUnits, Qgis::DistanceUnit mapUnits, double mapUnitsPerPixel=1.0)
Returns scale factor for conversion to map units.
 
Qgis::DistanceUnit mapUnits() const
Retrieve map units.
 
double symbologyScale() const
Returns the reference scale for output.
 
void clipValueToMapUnitScale(double &value, const QgsMapUnitScale &scale, double pixelToMMFactor) const
Clips value to scale minimum/maximum.
 
RAII class to pop scope from an expression context on destruction.
 
Single scope for storing variables and functions for use within a QgsExpressionContext.
 
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
 
static const QString EXPR_GEOMETRY_POINT_COUNT
Inbuilt variable name for point count variable.
 
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
 
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
 
static const QString EXPR_GEOMETRY_RING_NUM
Inbuilt variable name for geometry ring number variable.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
bool isCanceled() const
Tells whether the operation has been canceled already.
 
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
 
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
 
A line symbol layer type which fills a stroked line with a QgsFillSymbol.
 
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
 
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
 
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
 
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
 
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
 
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
 
QString layerType() const override
Returns a string that represents this layer type.
 
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFilledLineSymbolLayer, using the settings serialized in the properties map (correspo...
 
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
 
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
 
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
 
~QgsFilledLineSymbolLayer() override
 
QgsFilledLineSymbolLayer(double width=DEFAULT_SIMPLELINE_WIDTH, QgsFillSymbol *fillSymbol=nullptr)
Constructor for QgsFilledLineSymbolLayer.
 
void setMapUnitScale(const QgsMapUnitScale &scale) override
 
void setColor(const QColor &c) override
Sets the "representative" color for the symbol layer.
 
QColor color() const override
Returns the "representative" color of the symbol layer.
 
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
 
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
 
QgsFilledLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
 
QgsMapUnitScale mapUnitScale() const override
 
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
 
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
 
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
 
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
 
static bool segmentIntersection(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
 
A geometry is the spatial representation of a feature.
 
QVector< QgsGeometry > coerceToType(Qgis::WkbType type, double defaultZ=0, double defaultM=0) const
Attempts to coerce this geometry into the specified destination type.
 
static geos::unique_ptr offsetCurve(const GEOSGeometry *geometry, double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit, QString *errorMsg=nullptr)
Directly calculates the offset curve for a GEOS geometry object and returns a GEOS geometry result.
 
QgsAbstractGeometry * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
 
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlags())
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
 
static std::unique_ptr< QgsAbstractGeometry > fromGeos(const GEOSGeometry *geos)
Create a geometry from a GEOSGeometry.
 
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
 
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
 
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
 
void addStopsToGradient(QGradient *gradient, double opacity=1) const
Copy color ramp stops to a QGradient.
 
Line symbol layer type which draws repeating line sections along a line feature.
 
double hashAngle() const
Returns the angle to use when drawing the hashed lines sections, in degrees clockwise.
 
QgsHashedLineSymbolLayer(bool rotateSymbol=true, double interval=3)
Constructor for QgsHashedLineSymbolLayer.
 
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
 
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
 
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
 
void setWidth(double width) override
Sets the width of the line symbol layer.
 
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
 
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
 
double width() const override
Returns the estimated width for the line symbol layer.
 
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
 
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
 
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
 
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsHashedLineSymbolLayer, using the settings serialized in the properties map (correspo...
 
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
 
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
 
QgsHashedLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
 
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
 
~QgsHashedLineSymbolLayer() override
 
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
 
QColor color() const override
Returns the "representative" color of the symbol layer.
 
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
 
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
 
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
 
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
 
QString layerType() const override
Returns a string that represents this layer type.
 
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
 
void setHashAngle(double angle)
Sets the angle to use when drawing the hashed lines sections, in degrees clockwise.
 
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
 
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
 
static void overlayColor(QImage &image, const QColor &color)
Overlays a color onto an image.
 
Line string geometry type, with support for z-dimension and m-values.
 
static std::unique_ptr< QgsLineString > fromQPolygonF(const QPolygonF &polygon)
Returns a new linestring from a QPolygonF polygon input.
 
Abstract base class for line symbol layers.
 
Qgis::RenderUnit mOffsetUnit
 
RenderRingFilter
Options for filtering rings when the line symbol layer is being used to render a polygon's rings.
 
@ ExteriorRingOnly
Render the exterior ring only.
 
@ InteriorRingsOnly
Render the interior rings only.
 
@ AllRings
Render both exterior and interior rings.
 
QgsMapUnitScale mWidthMapUnitScale
 
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
 
void setWidthMapUnitScale(const QgsMapUnitScale &scale)
 
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
 
Qgis::RenderUnit mWidthUnit
 
void setOffset(double offset)
Sets the line's offset.
 
RenderRingFilter mRingFilter
 
void setOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the line's offset.
 
void setWidthUnit(Qgis::RenderUnit unit)
Sets the units for the line's width.
 
virtual double width() const
Returns the estimated width for the line symbol layer.
 
QgsMapUnitScale mOffsetMapUnitScale
 
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the line's offset.
 
QgsMapUnitScale mapUnitScale() const override
 
void setRingFilter(QgsLineSymbolLayer::RenderRingFilter filter)
Sets the line symbol layer's ring filter, which controls which rings are rendered when the line symbo...
 
void setMapUnitScale(const QgsMapUnitScale &scale) override
 
double offset() const
Returns the line's offset.
 
Qgis::RenderUnit offsetUnit() const
Returns the units for the line's offset.
 
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
 
A line symbol type, for rendering LineString and MultiLineString geometries.
 
Line symbol layer type which draws a gradient pattern perpendicularly along a line.
 
std::unique_ptr< QgsColorRamp > mGradientRamp
 
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
 
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp used for the gradient line.
 
QColor color2() const
Returns the color for endpoint of gradient, only used if the gradient color type is set to SimpleTwoC...
 
Qgis::GradientColorSource mGradientColorType
 
QString layerType() const override
Returns a string that represents this layer type.
 
~QgsLineburstSymbolLayer() override
 
QgsLineburstSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
 
void setMapUnitScale(const QgsMapUnitScale &scale) override
 
QgsMapUnitScale mapUnitScale() const override
 
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
 
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
 
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsLineburstSymbolLayer, using the settings serialized in the properties map (correspon...
 
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
 
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
 
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
 
QgsLineburstSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, const QColor &color2=Qt::white)
Constructor for QgsLineburstSymbolLayer, with the specified start and end gradient colors.
 
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
 
QgsColorRamp * colorRamp()
Returns the color ramp used for the gradient line.
 
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
 
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
 
Perform transforms between map coordinates and device coordinates.
 
double mapUnitsPerPixel() const
Returns the current map units per pixel.
 
void transformInPlace(double &x, double &y) const
Transforms map coordinates to device coordinates.
 
Struct for storing maximum and minimum scales for measurements in map units.
 
Line symbol layer type which draws repeating marker symbols along a line feature.
 
Q_DECL_DEPRECATED bool rotateMarker() const
Shall the marker be rotated.
 
std::unique_ptr< QgsMarkerSymbol > mMarker
 
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
 
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
 
QgsMarkerLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
 
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
 
void setDataDefinedProperty(QgsSymbolLayer::Property key, const QgsProperty &property) override
Sets a data defined property for the layer.
 
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
 
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
 
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
 
double symbolAngle() const override
Returns the symbol's current angle, in degrees clockwise.
 
double width() const override
Returns the estimated width for the line symbol layer.
 
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
 
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsMarkerLineSymbolLayer, using the settings serialized in the properties map (correspo...
 
QgsMarkerLineSymbolLayer(bool rotateMarker=DEFAULT_MARKERLINE_ROTATE, double interval=DEFAULT_MARKERLINE_INTERVAL)
Constructor for QgsMarkerLineSymbolLayer.
 
void setWidth(double width) override
Sets the width of the line symbol layer.
 
QColor color() const override
Returns the "representative" color of the symbol layer.
 
void setSymbolLineAngle(double angle) override
Sets the line angle modification for the symbol's angle.
 
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
 
~QgsMarkerLineSymbolLayer() override
 
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
 
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
 
QString layerType() const override
Returns a string that represents this layer type.
 
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
 
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsMarkerLineSymbolLayer from an SLD XML DOM element.
 
void setSymbolAngle(double angle) override
Sets the symbol's angle, in degrees clockwise.
 
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
 
void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false) override
Renders the templated symbol at the specified point, using the given render context.
 
Abstract base class for marker symbol layers.
 
A marker symbol type, for rendering Point and MultiPoint geometries.
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
 
Resolves relative paths into absolute paths and vice versa.
 
A class to represent a 2D point.
 
QgsPointXY project(double distance, double bearing) const
Returns a new point which corresponds to this point projected by a specified distance in a specified ...
 
Point geometry type, with support for z-dimension and m-values.
 
QPointF toQPointF() const
Returns the point as a QPointF.
 
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
 
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const final
Returns the calculated value of the property with the specified key from within the collection.
 
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
 
A store for object properties.
 
Line symbol layer type which draws line sections using a raster image file.
 
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
 
QgsRasterLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
 
double opacity() const
Returns the line opacity.
 
QString path() const
Returns the raster image path.
 
void setPath(const QString &path)
Set the raster image path.
 
QString layerType() const override
Returns a string that represents this layer type.
 
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
 
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
 
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
 
QgsRasterLineSymbolLayer(const QString &path=QString())
Constructor for QgsRasterLineSymbolLayer, with the specified raster image path.
 
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
 
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
 
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsRasterLineSymbolLayer, using the settings serialized in the properties map (correspo...
 
QColor color() const override
Returns the "representative" color of the symbol layer.
 
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
 
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
 
void setMapUnitScale(const QgsMapUnitScale &scale) override
 
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
 
QgsMapUnitScale mapUnitScale() const override
 
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
 
virtual ~QgsRasterLineSymbolLayer()
 
Contains information about the context of a rendering operation.
 
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
 
QgsVectorSimplifyMethod & vectorSimplifyMethod()
Returns the simplification settings to use when rendering vector layers.
 
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
 
QPainter * painter()
Returns the destination QPainter for the render operation.
 
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
 
QgsExpressionContext & expressionContext()
Gets the expression context.
 
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
 
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
 
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
 
QColor selectionColor() const
Returns the color to use when rendering selected features.
 
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
 
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
 
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
 
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
 
const QgsAbstractGeometry * geometry() const
Returns pointer to the unsegmentized geometry.
 
Scoped object for saving and restoring a QPainter object's state.
 
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...
 
Qgis::SymbolLayerFlags flags() const override
Returns flags which control the symbol layer's behavior.
 
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
 
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
 
QgsMapUnitScale mapUnitScale() const override
 
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
 
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
 
QVector< qreal > customDashVector() const
Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ...
 
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
 
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the outline of polygon, using the given render context.
 
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
 
void setCustomDashPatternMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for lengths used in the custom dash pattern.
 
void setTrimDistanceEndMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the end of the line.
 
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
 
void setTrimDistanceEnd(double distance)
Sets the trim distance for the end of the line, which dictates a length from the end of the line at w...
 
double dxfOffset(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets offset.
 
QgsSimpleLineSymbolLayer(const QColor &color=DEFAULT_SIMPLELINE_COLOR, double width=DEFAULT_SIMPLELINE_WIDTH, Qt::PenStyle penStyle=DEFAULT_SIMPLELINE_PENSTYLE)
Constructor for QgsSimpleLineSymbolLayer.
 
~QgsSimpleLineSymbolLayer() override
 
void setUseCustomDashPattern(bool b)
Sets whether the line uses a custom dash pattern.
 
void setTweakDashPatternOnCorners(bool enabled)
Sets whether dash patterns tweaks should be applied on sharp corners, to ensure that a double-length ...
 
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
 
void setCustomDashVector(const QVector< qreal > &vector)
Sets the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ren...
 
void setDashPatternOffset(double offset)
Sets the dash pattern offset, which dictates how far along the dash pattern the pattern should start ...
 
QColor dxfColor(QgsSymbolRenderContext &context) const override
Gets color.
 
QString layerType() const override
Returns a string that represents this layer type.
 
void setDashPatternOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the dash pattern offset.
 
QgsSimpleLineSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
 
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
 
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
 
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
 
void setAlignDashPattern(bool enabled)
Sets whether dash patterns should be aligned to the start and end of lines, by applying subtle tweaks...
 
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleLineSymbolLayer from an SLD XML DOM element.
 
double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets line width.
 
void setTrimDistanceStartMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the trim distance for the start of the line.
 
QVector< qreal > dxfCustomDashPattern(Qgis::RenderUnit &unit) const override
Gets dash pattern.
 
Qt::PenCapStyle penCapStyle() const
Returns the pen cap style used to render the line (e.g.
 
void setTrimDistanceEndUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the end of the line.
 
void setDashPatternOffsetUnit(Qgis::RenderUnit unit)
Sets the unit for the dash pattern offset.
 
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
 
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
 
void setMapUnitScale(const QgsMapUnitScale &scale) override
 
void setTrimDistanceStart(double distance)
Sets the trim distance for the start of the line, which dictates a length from the start of the line ...
 
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
 
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
 
void setTrimDistanceStartUnit(Qgis::RenderUnit unit)
Sets the unit for the trim distance for the start of the line.
 
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
 
void setCustomDashPatternUnit(Qgis::RenderUnit unit)
Sets the unit for lengths used in the custom dash pattern.
 
static QString encodePenStyle(Qt::PenStyle style)
 
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
 
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
 
static bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
 
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
 
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
 
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
 
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
 
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
 
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
 
static QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
 
static QVector< qreal > decodeRealVector(const QString &s)
 
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
 
static QString encodePenCapStyle(Qt::PenCapStyle style)
 
static 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 Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
 
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
 
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
 
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
 
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
 
static Qt::PenStyle decodePenStyle(const QString &str)
 
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
 
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
 
static QgsStringMap getVendorOptionList(QDomElement &element)
 
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
 
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
 
static QString encodeRealVector(const QVector< qreal > &v)
 
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
 
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
 
bool shouldRenderUsingSelectionColor(const QgsSymbolRenderContext &context) const
Returns true if the symbol layer should be rendered using the selection color from the render context...
 
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
 
bool installMasks(QgsRenderContext &context, bool recursive, const QRectF &rect=QRectF())
When rendering, install masks on context painter.
 
void removeMasks(QgsRenderContext &context, bool recursive)
When rendering, remove previously installed masks from context painter if recursive is true masks are...
 
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
 
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
 
Property
Data definable properties.
 
@ SecondaryColor
Secondary color (eg for gradient fills)
 
@ File
Filename, eg for svg files.
 
@ DashPatternOffset
Dash pattern offset,.
 
@ OffsetAlongLine
Offset along line.
 
@ CustomDash
Custom dash pattern.
 
@ StrokeStyle
Stroke style (eg solid, dashed)
 
@ StrokeColor
Stroke color.
 
@ TrimStart
Trim distance from start of line.
 
@ CapStyle
Line cap style.
 
@ Placement
Line marker placement.
 
@ LineAngle
Line angle, or angle of hash lines for hash line symbols.
 
@ JoinStyle
Line join style.
 
@ AverageAngleLength
Length to average symbol angles over.
 
@ Interval
Line marker interval.
 
@ StrokeWidth
Stroke width.
 
@ LineDistance
Distance between lines, or length of lines for hash line symbols.
 
@ TrimEnd
Trim distance from end of line.
 
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
 
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
 
virtual QString layerType() const =0
Returns a string that represents this layer type.
 
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
 
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
 
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
 
virtual QColor color() const
Returns the "representative" color of the symbol layer.
 
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
 
virtual Qgis::SymbolLayerFlags flags() const
Returns flags which control the symbol layer's behavior.
 
QgsPropertyCollection mDataDefinedProperties
 
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
 
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
 
const QgsFeature * feature() const
Returns the current feature being rendered.
 
Qgis::GeometryType originalGeometryType() const
Returns the geometry type for the original feature geometry being rendered.
 
QgsFields fields() const
Fields of the layer.
 
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
 
qreal opacity() const
Returns the opacity for the symbol.
 
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
 
Abstract base class for all rendered symbols.
 
qreal opacity() const
Returns the opacity for the symbol.
 
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
 
QColor color() const
Returns the symbol's color.
 
Qgis::SymbolType type() const
Returns the symbol's type.
 
Base class for templated line symbols, e.g.
 
bool rotateSymbols() const
Returns true if the repeating symbols be rotated to match their line segment orientation.
 
Qgis::RenderUnit outputUnit() const FINAL
Returns the units to use for sizes and widths within the symbol layer.
 
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
 
static void setCommonProperties(QgsTemplatedLineSymbolLayerBase *destLayer, const QVariantMap &properties)
Sets all common symbol properties in the destLayer, using the settings serialized in the properties m...
 
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
 
QgsMapUnitScale mapUnitScale() const FINAL
 
void setMapUnitScale(const QgsMapUnitScale &scale) FINAL
 
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
 
void setIntervalUnit(Qgis::RenderUnit unit)
Sets the units for the interval between symbols.
 
void setAverageAngleUnit(Qgis::RenderUnit unit)
Sets the unit for the length over which the line's direction is averaged when calculating individual ...
 
double interval() const
Returns the interval between individual symbols.
 
void setOffsetAlongLineUnit(Qgis::RenderUnit unit)
Sets the unit used for calculating the offset along line for symbols.
 
void setAverageAngleMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the length over which the line's direction is averaged when calculating i...
 
const QgsMapUnitScale & intervalMapUnitScale() const
Returns the map unit scale for the interval between symbols.
 
double offsetAlongLine() const
Returns the offset along the line for the symbol placement.
 
~QgsTemplatedLineSymbolLayerBase() override
 
void copyTemplateSymbolProperties(QgsTemplatedLineSymbolLayerBase *destLayer) const
Copies all common properties of this layer to another templated symbol layer.
 
Qgis::MarkerLinePlacements placements() const
Returns the placement of the symbols.
 
void setOffsetAlongLine(double offsetAlongLine)
Sets the the offset along the line for the symbol placement.
 
void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) FINAL
Renders the line symbol layer along the outline of polygon, using the given render context.
 
Qgis::RenderUnit offsetAlongLineUnit() const
Returns the unit used for calculating the offset along line for symbols.
 
QgsTemplatedLineSymbolLayerBase(bool rotateSymbol=true, double interval=3)
Constructor for QgsTemplatedLineSymbolLayerBase.
 
virtual void setSymbolLineAngle(double angle)=0
Sets the line angle modification for the symbol's angle.
 
void setInterval(double interval)
Sets the interval between individual symbols.
 
Qgis::RenderUnit intervalUnit() const
Returns the units for the interval between symbols.
 
Q_DECL_DEPRECATED Qgis::MarkerLinePlacement placement() const
Returns the placement of the symbols.
 
void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context) override
Renders the line symbol layer along the line joining points, using the given render context.
 
void setPlaceOnEveryPart(bool respect)
Sets whether the placement applies for every part of multi-part feature geometries.
 
void setPlacements(Qgis::MarkerLinePlacements placements)
Sets the placement of the symbols.
 
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
 
Qgis::RenderUnit averageAngleUnit() const
Returns the unit for the length over which the line's direction is averaged when calculating individu...
 
Q_DECL_DEPRECATED void setPlacement(Qgis::MarkerLinePlacement placement)
Sets the placement of the symbols.
 
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
 
const QgsMapUnitScale & offsetAlongLineMapUnitScale() const
Returns the map unit scale used for calculating the offset in map units along line for symbols.
 
virtual void renderSymbol(const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer=-1, bool selected=false)=0
Renders the templated symbol at the specified point, using the given render context.
 
void setIntervalMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the interval between symbols.
 
void setOffsetAlongLineMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale used for calculating the offset in map units along line for symbols.
 
void setAverageAngleLength(double length)
Sets the length of line over which the line's direction is averaged when calculating individual symbo...
 
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
 
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
 
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
 
Qgis::VectorRenderingSimplificationFlags simplifyHints() const
Gets the simplification hints of the vector layer managed.
 
float threshold() const
Gets the simplification threshold of the vector layer managed.
 
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
 
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
 
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
 
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
 
QMap< QString, QString > QgsStringMap
 
#define DEFAULT_MARKERLINE_INTERVAL
 
#define DEFAULT_SIMPLELINE_WIDTH
 
#define DEFAULT_MARKERLINE_ROTATE
 
#define DEFAULT_SIMPLELINE_PENSTYLE
 
#define DEFAULT_SIMPLELINE_COLOR
 
#define QgsDebugMsgLevel(str, level)
 
QList< QgsSymbolLayer * > QgsSymbolLayerList
 
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
 
Single variable definition for use within a QgsExpressionContextScope.
 
Utility class for identifying a unique vertex within a geometry.
 
Qgis::VertexType type
Vertex type.