Skip to content

Commit

Permalink
Arrow symbol layer: option to repeat or not the arrow on the line
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugo Mercier committed Jun 2, 2016
1 parent 6c9b588 commit efd32ff
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 145 deletions.
5 changes: 5 additions & 0 deletions python/core/symbology-ng/qgsarrowsymbollayer.sip
Expand Up @@ -85,6 +85,11 @@ class QgsArrowSymbolLayer : public QgsLineSymbolLayerV2
/** Set whether it is a curved arrow or a straight one */
void setIsCurved( bool isCurved );

/** Return whether the arrow is repeated along the line or not */
bool isRepeated() const;
/** Set whether the arrow is repeated along the line */
void setIsRepeated( bool isRepeated );

/** Possible head types */
enum HeadType
{
Expand Down
83 changes: 67 additions & 16 deletions src/core/symbology-ng/qgsarrowsymbollayer.cpp
Expand Up @@ -28,6 +28,7 @@ QgsArrowSymbolLayer::QgsArrowSymbolLayer()
, mHeadType( HeadSingle )
, mArrowType( ArrowPlain )
, mIsCurved( true )
, mIsRepeated( true )
, mScaledArrowWidth( 1.0 )
, mScaledArrowStartWidth( 1.0 )
, mScaledHeadWidth( 1.5 )
Expand Down Expand Up @@ -78,6 +79,9 @@ QgsSymbolLayerV2* QgsArrowSymbolLayer::create( const QgsStringMap& props )
if ( props.contains( "is_curved" ) )
l->setIsCurved( props["is_curved"].toInt() == 1 );

if ( props.contains( "is_repeated" ) )
l->setIsRepeated( props["is_repeated"].toInt() == 1 );

if ( props.contains( "head_width" ) )
l->setHeadWidth( props["head_width"].toDouble() );

Expand Down Expand Up @@ -145,6 +149,7 @@ QgsStringMap QgsArrowSymbolLayer::properties() const
map["arrow_start_width_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( arrowStartWidthUnitScale() );

map["is_curved"] = QString::number( isCurved() ? 1 : 0 );
map["is_repeated"] = QString::number( isRepeated() ? 1 : 0 );

map["head_width"] = QString::number( headWidth() );
map["head_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( headWidthUnit() );
Expand Down Expand Up @@ -689,52 +694,98 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF& points, QgsSymbolV2Re
mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, 1 );
if ( isCurved() )
{
for ( int pIdx = 0; pIdx < points.size() - 1; pIdx += 2 )
{
mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 );
_resolveDataDefined( context );
_resolveDataDefined( context );

if ( points.size() - pIdx >= 3 )
if ( ! isRepeated() )
{
if ( points.size() >= 3 )
{
// origin point
QPointF po( points.at( pIdx ) );
QPointF po( points.at( 0 ) );
// middle point
QPointF pm( points.at( pIdx + 1 ) );
QPointF pm( points.at( points.size() / 2 ) );
// destination point
QPointF pd( points.at( pIdx + 2 ) );
QPointF pd( points.back() );

QPolygonF poly = curvedArrow( po, pm, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
}
// straight arrow
else if ( points.size() - pIdx == 2 )
else if ( points.size() == 2 )
{
// origin point
QPointF po( points.at( pIdx ) );
QPointF po( points.at( 0 ) );
// destination point
QPointF pd( points.at( pIdx + 1 ) );
QPointF pd( points.at( 1 ) );

QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
}
}
else
{
for ( int pIdx = 0; pIdx < points.size() - 1; pIdx += 2 )
{
mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 );
_resolveDataDefined( context );

if ( points.size() - pIdx >= 3 )
{
// origin point
QPointF po( points.at( pIdx ) );
// middle point
QPointF pm( points.at( pIdx + 1 ) );
// destination point
QPointF pd( points.at( pIdx + 2 ) );

QPolygonF poly = curvedArrow( po, pm, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
}
// straight arrow
else if ( points.size() - pIdx == 2 )
{
// origin point
QPointF po( points.at( pIdx ) );
// destination point
QPointF pd( points.at( pIdx + 1 ) );

QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
}
}
}
}
else
{
// only straight arrows
for ( int pIdx = 0; pIdx < points.size() - 1; pIdx++ )
if ( !isRepeated() )
{
mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 );
_resolveDataDefined( context );

// origin point
QPointF po( points.at( pIdx ) );
QPointF po( points.at( 0 ) );
// destination point
QPointF pd( points.at( pIdx + 1 ) );
QPointF pd( points.back() );

QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
}
else
{
// only straight arrows
for ( int pIdx = 0; pIdx < points.size() - 1; pIdx++ )
{
mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 );
_resolveDataDefined( context );

// origin point
QPointF po( points.at( pIdx ) );
// destination point
QPointF pd( points.at( pIdx + 1 ) );

QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
}
}
}
context.renderContext().expressionContext().popScope();
}
Expand Down
6 changes: 6 additions & 0 deletions src/core/symbology-ng/qgsarrowsymbollayer.h
Expand Up @@ -105,6 +105,11 @@ class CORE_EXPORT QgsArrowSymbolLayer : public QgsLineSymbolLayerV2
/** Set whether it is a curved arrow or a straight one */
void setIsCurved( bool isCurved ) { mIsCurved = isCurved; }

/** Return whether the arrow is repeated along the line or not */
bool isRepeated() const { return mIsRepeated; }
/** Set whether the arrow is repeated along the line */
void setIsRepeated( bool isRepeated ) { mIsRepeated = isRepeated; }

/** Possible head types */
enum HeadType
{
Expand Down Expand Up @@ -178,6 +183,7 @@ class CORE_EXPORT QgsArrowSymbolLayer : public QgsLineSymbolLayerV2
HeadType mHeadType;
ArrowType mArrowType;
bool mIsCurved;
bool mIsRepeated;

double mScaledArrowWidth;
double mScaledArrowStartWidth;
Expand Down
10 changes: 10 additions & 0 deletions src/gui/symbology-ng/qgsarrowsymbollayerwidget.cpp
Expand Up @@ -64,6 +64,7 @@ void QgsArrowSymbolLayerWidget::setSymbolLayer( QgsSymbolLayerV2* layer )
mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );

mCurvedArrowChck->setChecked( mLayer->isCurved() );
mRepeatArrowChck->setChecked( mLayer->isRepeated() );

registerDataDefinedButton( mArrowWidthDDBtn, "arrow_width", QgsDataDefinedButton::Double, QgsDataDefinedButton::doubleDesc() );
registerDataDefinedButton( mArrowStartWidthDDBtn, "arrow_start_width", QgsDataDefinedButton::Double, QgsDataDefinedButton::doubleDesc() );
Expand Down Expand Up @@ -207,3 +208,12 @@ void QgsArrowSymbolLayerWidget::on_mCurvedArrowChck_stateChanged( int state )
mLayer->setIsCurved( state == Qt::Checked );
emit changed();
}

void QgsArrowSymbolLayerWidget::on_mRepeatArrowChck_stateChanged( int state )
{
if ( ! mLayer )
return;

mLayer->setIsRepeated( state == Qt::Checked );
emit changed();
}
1 change: 1 addition & 0 deletions src/gui/symbology-ng/qgsarrowsymbollayerwidget.h
Expand Up @@ -63,6 +63,7 @@ class GUI_EXPORT QgsArrowSymbolLayerWidget: public QgsSymbolLayerV2Widget, priva
void on_mOffsetUnitWidget_changed();

void on_mCurvedArrowChck_stateChanged( int );
void on_mRepeatArrowChck_stateChanged( int );
};

#endif

0 comments on commit efd32ff

Please sign in to comment.