Skip to content

Commit

Permalink
Fix @geometry_point_num and @geometry_point_count for marker lines
Browse files Browse the repository at this point in the history
Fixes #15673
  • Loading branch information
nyalldawson committed Oct 10, 2016
1 parent 748d8ac commit ddfe91f
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/core/symbology-ng/qgslinesymbollayer.cpp
Expand Up @@ -933,6 +933,9 @@ void QgsMarkerLineSymbolLayer::renderPolylineInterval( const QPolygonF& points,
QgsRenderContext& rc = context.renderContext();
double interval = mInterval;

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

if ( hasDataDefinedProperty( QgsSymbolLayer::EXPR_INTERVAL ) )
{
context.setOriginalValueVariable( mInterval );
Expand All @@ -952,6 +955,7 @@ void QgsMarkerLineSymbolLayer::renderPolylineInterval( const QPolygonF& points,
double painterUnitInterval = QgsSymbolLayerUtils::convertToPainterUnits( rc, interval, mIntervalUnit, mIntervalMapUnitScale );
lengthLeft = painterUnitInterval - QgsSymbolLayerUtils::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 @@ -982,12 +986,15 @@ void QgsMarkerLineSymbolLayer::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 @@ -1011,6 +1018,10 @@ void QgsMarkerLineSymbolLayer::renderPolylineVertex( const QPolygonF& points, Qg
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( QgsSymbolLayer::EXPR_OFFSET_ALONG_LINE ) )
{
Expand All @@ -1033,8 +1044,11 @@ void QgsMarkerLineSymbolLayer::renderPolylineVertex( const QPolygonF& points, Qg
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 @@ -1056,6 +1070,8 @@ void QgsMarkerLineSymbolLayer::renderPolylineVertex( const QPolygonF& points, Qg
mMarker->renderPoint( mapPoint, context.feature(), rc, -1, context.selected() );
}
}

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

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

Expand All @@ -1088,11 +1105,16 @@ void QgsMarkerLineSymbolLayer::renderPolylineVertex( const QPolygonF& points, Qg
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 @@ -1109,6 +1131,8 @@ void QgsMarkerLineSymbolLayer::renderPolylineVertex( const QPolygonF& points, Qg

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

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

double QgsMarkerLineSymbolLayer::markerAngle( const QPolygonF& points, bool isRing, int vertex )
Expand Down
65 changes: 65 additions & 0 deletions tests/src/core/testqgsmarkerlinesymbol.cpp
Expand Up @@ -28,6 +28,10 @@
#include "qgsapplication.h"
#include "qgspallabeling.h"
#include "qgsfontutils.h"
#include "qgslinesymbollayer.h"
#include "qgssinglesymbolrenderer.h"
#include "qgsmarkersymbollayer.h"
#include "qgsdatadefined.h"

//qgis unit test includes
#include <qgsrenderchecker.h>
Expand Down Expand Up @@ -55,6 +59,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 @@ -136,6 +142,65 @@ void TestQgsMarkerLineSymbol::lineOffset()
// http://hub.qgis.org/issues/13811#note-1
}

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

QgsMarkerLineSymbolLayer* ml = new QgsMarkerLineSymbolLayer();
ml->setPlacement( QgsMarkerLineSymbolLayer::Interval );
ml->setInterval( 4 );
QgsLineSymbol* lineSymbol = new QgsLineSymbol();
lineSymbol->changeSymbolLayer( 0, ml );
QgsSingleSymbolRenderer* r = new QgsSingleSymbolRenderer( lineSymbol );

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

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

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

mLinesLayer->setRenderer( r );

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

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

QgsMarkerLineSymbolLayer* ml = new QgsMarkerLineSymbolLayer();
ml->setPlacement( QgsMarkerLineSymbolLayer::Vertex );
QgsLineSymbol* lineSymbol = new QgsLineSymbol();
lineSymbol->changeSymbolLayer( 0, ml );
QgsSingleSymbolRenderer* r = new QgsSingleSymbolRenderer( lineSymbol );

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

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

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

mLinesLayer->setRenderer( 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.

0 comments on commit ddfe91f

Please sign in to comment.