Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[symbology] improve marker rotation along line to fix data-defined
angle support
  • Loading branch information
nirvn authored and nyalldawson committed May 19, 2015
1 parent 4b4075b commit f314522
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 24 deletions.
8 changes: 8 additions & 0 deletions python/core/symbology-ng/qgssymbollayerv2.sip
Expand Up @@ -317,6 +317,14 @@ class QgsMarkerSymbolLayerV2 : QgsSymbolLayerV2

void setAngle( double angle );
double angle() const;

/** Sets the line angle modification for the symbol's angle. This angle is added to
* the marker's rotation and data defined rotation before rendering the symbol, and
* is usually used for orienting symbols to match a line's angle.
* @param lineangle Angle in degrees, valid values are between 0 and 360
* @note added in QGIS 2.9
*/
void setLineAngle( double lineAngle );

void setSize( double size );
double size() const;
Expand Down
8 changes: 8 additions & 0 deletions python/core/symbology-ng/qgssymbolv2.sip
Expand Up @@ -236,6 +236,14 @@ class QgsMarkerSymbolV2 : QgsSymbolV2

void setAngle( double angle );
double angle();

/** Sets the line angle modification for the symbol's angle. This angle is added to
* the marker's rotation and data defined rotation before rendering the symbol, and
* is usually used for orienting symbols to match a line's angle.
* @param lineangle Angle in degrees, valid values are between 0 and 360
* @note added in QGIS 2.9
*/
void setLineAngle( double lineAngle );

void setSize( double size );
double size();
Expand Down
12 changes: 6 additions & 6 deletions src/core/symbology-ng/qgsellipsesymbollayerv2.cpp
Expand Up @@ -251,11 +251,11 @@ void QgsEllipseSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2Rend
double rotation = 0.0;
if ( hasDataDefinedProperty( "rotation" ) )
{
rotation = evaluateDataDefinedProperty( "rotation", context.feature(), mAngle ).toDouble();
rotation = evaluateDataDefinedProperty( "rotation", context.feature(), mAngle ).toDouble() + mLineAngle;
}
else if ( !qgsDoubleNear( mAngle, 0.0 ) )
else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
{
rotation = mAngle;
rotation = mAngle + mLineAngle;
}
if ( rotation )
off = _rotatedOffset( off, rotation );
Expand Down Expand Up @@ -630,11 +630,11 @@ bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFa
double rotation = 0.0;
if ( hasDataDefinedProperty( "rotation" ) )
{
rotation = evaluateDataDefinedProperty( "rotation", f, mAngle ).toDouble();
rotation = evaluateDataDefinedProperty( "rotation", f, mAngle ).toDouble() + mLineAngle;
}
else if ( !qgsDoubleNear( mAngle, 0.0 ) )
else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
{
rotation = mAngle;
rotation = mAngle + mLineAngle;
}
rotation = -rotation; //rotation in Qt is counterclockwise
if ( rotation )
Expand Down
7 changes: 1 addition & 6 deletions src/core/symbology-ng/qgslinesymbollayerv2.cpp
Expand Up @@ -881,7 +881,6 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points
QPointF lastPt = points[0];
double lengthLeft = 0; // how much is left until next marker
bool first = mOffsetAlongLine ? false : true; //only draw marker at first vertex when no offset along line is set
double origAngle = mMarker->angle();

QgsRenderContext& rc = context.renderContext();
double interval = mInterval;
Expand Down Expand Up @@ -923,7 +922,7 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points
// rotate marker (if desired)
if ( mRotateMarker )
{
mMarker->setAngle( origAngle + ( l.angle() * 180 / M_PI ) );
mMarker->setLineAngle( l.angle() * 180 / M_PI );
}

// draw first marker
Expand All @@ -945,10 +944,6 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points

lastPt = pt;
}

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

}

static double _averageAngle( const QPointF& prevPt, const QPointF& pt, const QPointF& nextPt )
Expand Down
24 changes: 12 additions & 12 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
Expand Up @@ -492,11 +492,11 @@ void QgsSimpleMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV
QPointF off( offsetX, offsetY );

//angle
double angle = mAngle;
double angle = mAngle + mLineAngle;
bool usingDataDefinedRotation = false;
if ( hasDataDefinedProperty( "angle" ) )
{
angle = evaluateDataDefinedProperty( "angle", context.feature(), mAngle, &ok ).toDouble();
angle = evaluateDataDefinedProperty( "angle", context.feature(), mAngle, &ok ).toDouble() + mLineAngle;
usingDataDefinedRotation = ok;
}

Expand Down Expand Up @@ -873,10 +873,10 @@ bool QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc
QPointF off( offsetX, offsetY );

//angle
double angle = mAngle;
double angle = mAngle + mLineAngle;
if ( context && hasDataDefinedProperty( "angle" ) )
{
angle = evaluateDataDefinedProperty( "angle", f, mAngle ).toDouble();
angle = evaluateDataDefinedProperty( "angle", f, mAngle ).toDouble() + mLineAngle;
}

angle = -angle; //rotation in Qt is counterclockwise
Expand Down Expand Up @@ -1271,10 +1271,10 @@ void QgsSvgMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2Re
markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
QPointF outputOffset( offsetX, offsetY );

double angle = mAngle;
double angle = mAngle + mLineAngle;
if ( hasDataDefinedProperty( "angle" ) )
{
angle = evaluateDataDefinedProperty( "angle", context.feature(), mAngle ).toDouble();
angle = evaluateDataDefinedProperty( "angle", context.feature(), mAngle ).toDouble() + mLineAngle;
}

bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || hasDataDefinedProperty( "angle" );
Expand Down Expand Up @@ -1603,10 +1603,10 @@ bool QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScale

QPointF outputOffset( offsetX, offsetY );

double angle = mAngle;
double angle = mAngle + mLineAngle;
if ( hasDataDefinedProperty( "angle" ) )
{
angle = evaluateDataDefinedProperty( "angle", f, mAngle ).toDouble();
angle = evaluateDataDefinedProperty( "angle", f, mAngle ).toDouble() + mLineAngle;
}
//angle = -angle; //rotation in Qt is counterclockwise
if ( angle )
Expand Down Expand Up @@ -1721,8 +1721,8 @@ void QgsFontMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2R
double offsetY = 0;
markerOffset( context, offsetX, offsetY );
QPointF outputOffset( offsetX, offsetY );
if ( mAngle )
outputOffset = _rotatedOffset( outputOffset, mAngle );
if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
outputOffset = _rotatedOffset( outputOffset, mAngle + mLineAngle );
p->translate( point + outputOffset );

if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale )
Expand All @@ -1731,8 +1731,8 @@ void QgsFontMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2R
p->scale( s, s );
}

if ( mAngle != 0 )
p->rotate( mAngle );
if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
p->rotate( mAngle + mLineAngle );

p->drawText( -mChrOffset, mChr );
p->restore();
Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgssymbollayerv2.cpp
Expand Up @@ -354,6 +354,7 @@ void QgsSymbolLayerV2::copyPaintEffect( QgsSymbolLayerV2 *destLayer ) const
QgsMarkerSymbolLayerV2::QgsMarkerSymbolLayerV2( bool locked )
: QgsSymbolLayerV2( QgsSymbolV2::Marker, locked )
, mAngle( 0 )
, mLineAngle( 0 )
, mSize( 2.0 )
, mSizeUnit( QgsSymbolV2::MM )
, mOffsetUnit( QgsSymbolV2::MM )
Expand Down
9 changes: 9 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2.h
Expand Up @@ -315,6 +315,14 @@ class CORE_EXPORT QgsMarkerSymbolLayerV2 : public QgsSymbolLayerV2
void setAngle( double angle ) { mAngle = angle; }
double angle() const { return mAngle; }

/** Sets the line angle modification for the symbol's angle. This angle is added to
* the marker's rotation and data defined rotation before rendering the symbol, and
* is usually used for orienting symbols to match a line's angle.
* @param lineangle Angle in degrees, valid values are between 0 and 360
* @note added in QGIS 2.9
*/
void setLineAngle( double lineAngle ) { mLineAngle = lineAngle; }

void setSize( double size ) { mSize = size; }
double size() const { return mSize; }

Expand Down Expand Up @@ -370,6 +378,7 @@ class CORE_EXPORT QgsMarkerSymbolLayerV2 : public QgsSymbolLayerV2
static QPointF _rotatedOffset( const QPointF& offset, double angle );

double mAngle;
double mLineAngle;
double mSize;
QgsSymbolV2::OutputUnit mSizeUnit;
QgsMapUnitScale mSizeMapUnitScale;
Expand Down
10 changes: 10 additions & 0 deletions src/core/symbology-ng/qgssymbolv2.cpp
Expand Up @@ -519,6 +519,7 @@ void QgsMarkerSymbolV2::setAngle( double ang )
}
}


double QgsMarkerSymbolV2::angle()
{
QgsSymbolLayerV2List::const_iterator it = mLayers.begin();
Expand All @@ -531,6 +532,15 @@ double QgsMarkerSymbolV2::angle()
return layer->angle();
}

void QgsMarkerSymbolV2::setLineAngle( double lineAng )
{
for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
{
QgsMarkerSymbolLayerV2* layer = ( QgsMarkerSymbolLayerV2* ) * it;
layer->setLineAngle( lineAng );
}
}

void QgsMarkerSymbolV2::setSize( double s )
{
double origSize = size();
Expand Down
8 changes: 8 additions & 0 deletions src/core/symbology-ng/qgssymbolv2.h
Expand Up @@ -282,6 +282,14 @@ class CORE_EXPORT QgsMarkerSymbolV2 : public QgsSymbolV2
void setAngle( double angle );
double angle();

/** Sets the line angle modification for the symbol's angle. This angle is added to
* the marker's rotation and data defined rotation before rendering the symbol, and
* is usually used for orienting symbols to match a line's angle.
* @param lineangle Angle in degrees, valid values are between 0 and 360
* @note added in QGIS 2.9
*/
void setLineAngle( double lineAngle );

void setSize( double size );
double size();

Expand Down

0 comments on commit f314522

Please sign in to comment.