Skip to content

Commit efd32ff

Browse files
author
Hugo Mercier
committed
Arrow symbol layer: option to repeat or not the arrow on the line
1 parent 6c9b588 commit efd32ff

File tree

8 files changed

+254
-145
lines changed

8 files changed

+254
-145
lines changed

python/core/symbology-ng/qgsarrowsymbollayer.sip

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ class QgsArrowSymbolLayer : public QgsLineSymbolLayerV2
8585
/** Set whether it is a curved arrow or a straight one */
8686
void setIsCurved( bool isCurved );
8787

88+
/** Return whether the arrow is repeated along the line or not */
89+
bool isRepeated() const;
90+
/** Set whether the arrow is repeated along the line */
91+
void setIsRepeated( bool isRepeated );
92+
8893
/** Possible head types */
8994
enum HeadType
9095
{

src/core/symbology-ng/qgsarrowsymbollayer.cpp

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ QgsArrowSymbolLayer::QgsArrowSymbolLayer()
2828
, mHeadType( HeadSingle )
2929
, mArrowType( ArrowPlain )
3030
, mIsCurved( true )
31+
, mIsRepeated( true )
3132
, mScaledArrowWidth( 1.0 )
3233
, mScaledArrowStartWidth( 1.0 )
3334
, mScaledHeadWidth( 1.5 )
@@ -78,6 +79,9 @@ QgsSymbolLayerV2* QgsArrowSymbolLayer::create( const QgsStringMap& props )
7879
if ( props.contains( "is_curved" ) )
7980
l->setIsCurved( props["is_curved"].toInt() == 1 );
8081

82+
if ( props.contains( "is_repeated" ) )
83+
l->setIsRepeated( props["is_repeated"].toInt() == 1 );
84+
8185
if ( props.contains( "head_width" ) )
8286
l->setHeadWidth( props["head_width"].toDouble() );
8387

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

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

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

697-
if ( points.size() - pIdx >= 3 )
699+
if ( ! isRepeated() )
700+
{
701+
if ( points.size() >= 3 )
698702
{
699703
// origin point
700-
QPointF po( points.at( pIdx ) );
704+
QPointF po( points.at( 0 ) );
701705
// middle point
702-
QPointF pm( points.at( pIdx + 1 ) );
706+
QPointF pm( points.at( points.size() / 2 ) );
703707
// destination point
704-
QPointF pd( points.at( pIdx + 2 ) );
708+
QPointF pd( points.back() );
705709

706710
QPolygonF poly = curvedArrow( po, pm, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
707711
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
708712
}
709713
// straight arrow
710-
else if ( points.size() - pIdx == 2 )
714+
else if ( points.size() == 2 )
711715
{
712716
// origin point
713-
QPointF po( points.at( pIdx ) );
717+
QPointF po( points.at( 0 ) );
714718
// destination point
715-
QPointF pd( points.at( pIdx + 1 ) );
719+
QPointF pd( points.at( 1 ) );
716720

717721
QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
718722
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
719723
}
720724
}
725+
else
726+
{
727+
for ( int pIdx = 0; pIdx < points.size() - 1; pIdx += 2 )
728+
{
729+
mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 );
730+
_resolveDataDefined( context );
731+
732+
if ( points.size() - pIdx >= 3 )
733+
{
734+
// origin point
735+
QPointF po( points.at( pIdx ) );
736+
// middle point
737+
QPointF pm( points.at( pIdx + 1 ) );
738+
// destination point
739+
QPointF pd( points.at( pIdx + 2 ) );
740+
741+
QPolygonF poly = curvedArrow( po, pm, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
742+
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
743+
}
744+
// straight arrow
745+
else if ( points.size() - pIdx == 2 )
746+
{
747+
// origin point
748+
QPointF po( points.at( pIdx ) );
749+
// destination point
750+
QPointF pd( points.at( pIdx + 1 ) );
751+
752+
QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
753+
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
754+
}
755+
}
756+
}
721757
}
722758
else
723759
{
724-
// only straight arrows
725-
for ( int pIdx = 0; pIdx < points.size() - 1; pIdx++ )
760+
if ( !isRepeated() )
726761
{
727-
mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 );
728762
_resolveDataDefined( context );
729763

730764
// origin point
731-
QPointF po( points.at( pIdx ) );
765+
QPointF po( points.at( 0 ) );
732766
// destination point
733-
QPointF pd( points.at( pIdx + 1 ) );
767+
QPointF pd( points.back() );
734768

735769
QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
736770
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
737771
}
772+
else
773+
{
774+
// only straight arrows
775+
for ( int pIdx = 0; pIdx < points.size() - 1; pIdx++ )
776+
{
777+
mExpressionScope->setVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, pIdx + 1 );
778+
_resolveDataDefined( context );
779+
780+
// origin point
781+
QPointF po( points.at( pIdx ) );
782+
// destination point
783+
QPointF pd( points.at( pIdx + 1 ) );
784+
785+
QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadWidth, mScaledHeadHeight, mComputedHeadType, mComputedArrowType, mScaledOffset );
786+
mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext() );
787+
}
788+
}
738789
}
739790
context.renderContext().expressionContext().popScope();
740791
}

src/core/symbology-ng/qgsarrowsymbollayer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ class CORE_EXPORT QgsArrowSymbolLayer : public QgsLineSymbolLayerV2
105105
/** Set whether it is a curved arrow or a straight one */
106106
void setIsCurved( bool isCurved ) { mIsCurved = isCurved; }
107107

108+
/** Return whether the arrow is repeated along the line or not */
109+
bool isRepeated() const { return mIsRepeated; }
110+
/** Set whether the arrow is repeated along the line */
111+
void setIsRepeated( bool isRepeated ) { mIsRepeated = isRepeated; }
112+
108113
/** Possible head types */
109114
enum HeadType
110115
{
@@ -178,6 +183,7 @@ class CORE_EXPORT QgsArrowSymbolLayer : public QgsLineSymbolLayerV2
178183
HeadType mHeadType;
179184
ArrowType mArrowType;
180185
bool mIsCurved;
186+
bool mIsRepeated;
181187

182188
double mScaledArrowWidth;
183189
double mScaledArrowStartWidth;

src/gui/symbology-ng/qgsarrowsymbollayerwidget.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ void QgsArrowSymbolLayerWidget::setSymbolLayer( QgsSymbolLayerV2* layer )
6464
mOffsetUnitWidget->setMapUnitScale( mLayer->offsetMapUnitScale() );
6565

6666
mCurvedArrowChck->setChecked( mLayer->isCurved() );
67+
mRepeatArrowChck->setChecked( mLayer->isRepeated() );
6768

6869
registerDataDefinedButton( mArrowWidthDDBtn, "arrow_width", QgsDataDefinedButton::Double, QgsDataDefinedButton::doubleDesc() );
6970
registerDataDefinedButton( mArrowStartWidthDDBtn, "arrow_start_width", QgsDataDefinedButton::Double, QgsDataDefinedButton::doubleDesc() );
@@ -207,3 +208,12 @@ void QgsArrowSymbolLayerWidget::on_mCurvedArrowChck_stateChanged( int state )
207208
mLayer->setIsCurved( state == Qt::Checked );
208209
emit changed();
209210
}
211+
212+
void QgsArrowSymbolLayerWidget::on_mRepeatArrowChck_stateChanged( int state )
213+
{
214+
if ( ! mLayer )
215+
return;
216+
217+
mLayer->setIsRepeated( state == Qt::Checked );
218+
emit changed();
219+
}

src/gui/symbology-ng/qgsarrowsymbollayerwidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class GUI_EXPORT QgsArrowSymbolLayerWidget: public QgsSymbolLayerV2Widget, priva
6363
void on_mOffsetUnitWidget_changed();
6464

6565
void on_mCurvedArrowChck_stateChanged( int );
66+
void on_mRepeatArrowChck_stateChanged( int );
6667
};
6768

6869
#endif

0 commit comments

Comments
 (0)