Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix @geometry_point_num and @geometry_point_count for marker lines
Fixes #15673

(cherry-picked from ddfe91f)
  • Loading branch information
nyalldawson committed Oct 12, 2016
1 parent 89e6904 commit edd56e9
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/core/symbology-ng/qgslinesymbollayerv2.cpp
Expand Up @@ -952,6 +952,9 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points
QgsRenderContext& rc = context.renderContext();
double interval = mInterval;

QgsExpressionContextScope* scope = new QgsExpressionContextScope();
context.renderContext().expressionContext().appendScope( scope );

if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_INTERVAL ) )
{
context.setOriginalValueVariable( mInterval );
Expand All @@ -971,6 +974,7 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points
double painterUnitInterval = QgsSymbolLayerV2Utils::convertToPainterUnits( rc, interval, mIntervalUnit, mIntervalMapUnitScale );
lengthLeft = painterUnitInterval - QgsSymbolLayerV2Utils::convertToPainterUnits( rc, offsetAlongLine, mIntervalUnit, mIntervalMapUnitScale );

int pointNum = 0;
for ( int i = 1; i < points.count(); ++i )
{
const QPointF& pt = points[i];
Expand Down Expand Up @@ -1001,12 +1005,15 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points
// "c" is 1 for regular point or in interval (0,1] for begin of line segment
lastPt += c * diff;
lengthLeft -= painterUnitInterval;
scope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, ++pointNum );
mMarker->renderPoint( lastPt, context.feature(), rc, -1, context.selected() );
c = 1; // reset c (if wasn't 1 already)
}

lastPt = pt;
}

delete context.renderContext().expressionContext().popScope();
}

static double _averageAngle( QPointF prevPt, QPointF pt, QPointF nextPt )
Expand All @@ -1030,6 +1037,10 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
int i, maxCount;
bool isRing = false;

QgsExpressionContextScope* scope = new QgsExpressionContextScope();
context.renderContext().expressionContext().appendScope( scope );
scope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT, points.size() );

double offsetAlongLine = mOffsetAlongLine;
if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET_ALONG_LINE ) )
{
Expand All @@ -1052,8 +1063,11 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
QgsPointV2 vPoint;
double x, y, z;
QPointF mapPoint;
int pointNum = 0;
while ( context.renderContext().geometry()->nextVertex( vId, vPoint ) )
{
scope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, ++pointNum );

if (( placement == Vertex && vId.type == QgsVertexId::SegmentVertex )
|| ( placement == CurvePoint && vId.type == QgsVertexId::CurveVertex ) )
{
Expand All @@ -1075,6 +1089,8 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
mMarker->renderPoint( mapPoint, context.feature(), rc, -1, context.selected() );
}
}

delete context.renderContext().expressionContext().popScope();
return;
}

Expand All @@ -1097,6 +1113,7 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
}
else
{
delete context.renderContext().expressionContext().popScope();
return;
}

Expand All @@ -1107,11 +1124,16 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
renderOffsetVertexAlongLine( points, i, distance, context );
// restore original rotation
mMarker->setAngle( origAngle );

delete context.renderContext().expressionContext().popScope();
return;
}

int pointNum = 0;
for ( ; i < maxCount; ++i )
{
scope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, ++pointNum );

if ( isRing && placement == Vertex && i == points.count() - 1 )
{
continue; // don't draw the last marker - it has been drawn already
Expand All @@ -1128,6 +1150,8 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,

// restore original rotation
mMarker->setAngle( origAngle );

delete context.renderContext().expressionContext().popScope();
}

double QgsMarkerLineSymbolLayerV2::markerAngle( const QPolygonF& points, bool isRing, int vertex )
Expand Down
65 changes: 65 additions & 0 deletions tests/src/core/testqgsmarkerlinesymbol.cpp
Expand Up @@ -29,6 +29,10 @@
#include "qgsmaprenderer.h"
#include "qgspallabeling.h"
#include "qgsfontutils.h"
#include "qgslinesymbollayerv2.h"
#include "qgssinglesymbolrendererv2.h"
#include "qgsmarkersymbollayerv2.h"
#include "qgsdatadefined.h"

//qgis unit test includes
#include <qgsrenderchecker.h>
Expand Down Expand Up @@ -56,6 +60,8 @@ class TestQgsMarkerLineSymbol : public QObject
void cleanup() {} // will be called after every testfunction.

void lineOffset();
void pointNumInterval();
void pointNumVertex();

private:
bool render( const QString& theFileName );
Expand Down Expand Up @@ -137,6 +143,65 @@ void TestQgsMarkerLineSymbol::lineOffset()
// http://hub.qgis.org/issues/13811#note-1
}

void TestQgsMarkerLineSymbol::pointNumInterval()
{
mMapSettings->setLayers( QStringList() << mLinesLayer->id() );

QgsMarkerLineSymbolLayerV2* ml = new QgsMarkerLineSymbolLayerV2();
ml->setPlacement( QgsMarkerLineSymbolLayerV2::Interval );
ml->setInterval( 4 );
QgsLineSymbolV2* lineSymbol = new QgsLineSymbolV2();
lineSymbol->changeSymbolLayer( 0, ml );
QgsSingleSymbolRendererV2* r = new QgsSingleSymbolRendererV2( lineSymbol );

// make sub-symbol
QgsStringMap props;
props["color"] = "255,0,0";
props["size"] = "2";
props["outline_style"] = "no";
QgsSimpleMarkerSymbolLayerV2* marker = static_cast< QgsSimpleMarkerSymbolLayerV2* >( QgsSimpleMarkerSymbolLayerV2::create( props ) );

marker->setDataDefinedProperty( "size", new QgsDataDefined( true, true, "@geometry_point_num * 2" ) );

QgsMarkerSymbolV2* subSymbol = new QgsMarkerSymbolV2();
subSymbol->changeSymbolLayer( 0, marker );
ml->setSubSymbol( subSymbol );

mLinesLayer->setRendererV2( r );

mMapSettings->setExtent( QgsRectangle( -140, -140, 140, 140 ) );
QVERIFY( render( "point_num_interval" ) );
}

void TestQgsMarkerLineSymbol::pointNumVertex()
{
mMapSettings->setLayers( QStringList() << mLinesLayer->id() );

QgsMarkerLineSymbolLayerV2* ml = new QgsMarkerLineSymbolLayerV2();
ml->setPlacement( QgsMarkerLineSymbolLayerV2::Vertex );
QgsLineSymbolV2* lineSymbol = new QgsLineSymbolV2();
lineSymbol->changeSymbolLayer( 0, ml );
QgsSingleSymbolRendererV2* r = new QgsSingleSymbolRendererV2( lineSymbol );

// make sub-symbol
QgsStringMap props;
props["color"] = "255,0,0";
props["size"] = "2";
props["outline_style"] = "no";
QgsSimpleMarkerSymbolLayerV2* marker = static_cast< QgsSimpleMarkerSymbolLayerV2* >( QgsSimpleMarkerSymbolLayerV2::create( props ) );

marker->setDataDefinedProperty( "size", new QgsDataDefined( true, true, "@geometry_point_num * 2" ) );

QgsMarkerSymbolV2* subSymbol = new QgsMarkerSymbolV2();
subSymbol->changeSymbolLayer( 0, marker );
ml->setSubSymbol( subSymbol );

mLinesLayer->setRendererV2( r );

mMapSettings->setExtent( QgsRectangle( -140, -140, 140, 140 ) );
QVERIFY( render( "point_num_vertex" ) );
}

bool TestQgsMarkerLineSymbol::render( const QString& theTestType )
{
mReport += "<h2>" + theTestType + "</h2>\n";
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit edd56e9

Please sign in to comment.