Skip to content

Commit 89e0a94

Browse files
author
wonder
committed
[FEATURE] Allow the marker line symbol layer draw markers on each vertex.
Developed for Faunalia (http://www.faunalia.it) with funding from Regione Toscana - Sistema Informativo per la Gestione del Territorio e dell' Ambiente [RT-SIGTA]. For the project: "Sviluppo di prodotti software GIS open-source basati sui prodotti QuantumGIS e Postgis (CIG 037728516E)" git-svn-id: http://svn.osgeo.org/qgis/trunk@14779 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent e7428cd commit 89e0a94

File tree

5 files changed

+145
-35
lines changed

5 files changed

+145
-35
lines changed

src/core/symbology-ng/qgslinesymbollayerv2.cpp

+66-3
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ QgsMarkerLineSymbolLayerV2::QgsMarkerLineSymbolLayerV2( bool rotateMarker, doubl
215215
mInterval = interval;
216216
mMarker = NULL;
217217
mOffset = 0;
218+
mPlacement = Interval;
218219

219220
setSubSymbol( new QgsMarkerSymbolV2() );
220221
}
@@ -237,6 +238,8 @@ QgsSymbolLayerV2* QgsMarkerLineSymbolLayerV2::create( const QgsStringMap& props
237238
QgsMarkerLineSymbolLayerV2* x = new QgsMarkerLineSymbolLayerV2( rotate, interval );
238239
if ( props.contains( "offset" ) )
239240
x->setOffset( props["offset"].toDouble() );
241+
if ( props.contains( "placement" ) )
242+
x->setPlacement( props["placement"] == "vertex" ? Vertex : Interval );
240243
return x;
241244
}
242245

@@ -276,16 +279,22 @@ void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSym
276279
{
277280
if ( mOffset == 0 )
278281
{
279-
renderPolylineNoOffset( points, context );
282+
if ( mPlacement == Vertex )
283+
renderPolylineVertex( points, context );
284+
else
285+
renderPolylineInterval( points, context );
280286
}
281287
else
282288
{
283289
QPolygonF points2 = ::offsetLine( points, context.outputLineWidth( mOffset ) );
284-
renderPolylineNoOffset( points2, context );
290+
if ( mPlacement == Vertex )
291+
renderPolylineVertex( points2, context );
292+
else
293+
renderPolylineInterval( points2, context );
285294
}
286295
}
287296

288-
void QgsMarkerLineSymbolLayerV2::renderPolylineNoOffset( const QPolygonF& points, QgsSymbolV2RenderContext& context )
297+
void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context )
289298
{
290299
QPointF lastPt = points[0];
291300
double lengthLeft = 0; // how much is left until next marker
@@ -344,12 +353,65 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineNoOffset( const QPolygonF& points
344353

345354
}
346355

356+
void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context )
357+
{
358+
QPointF lastPt = points[0];
359+
QgsRenderContext& rc = context.renderContext();
360+
361+
double origAngle = mMarker->angle();
362+
double angle;
363+
364+
for ( int i = 0; i < points.count(); ++i )
365+
{
366+
const QPointF& pt = points[i];
367+
368+
// rotate marker (if desired)
369+
if ( mRotateMarker )
370+
{
371+
if ( i == 0 )
372+
{
373+
const QPointF& nextPt = points[i+1];
374+
if ( pt == nextPt )
375+
continue;
376+
angle = MyLine( pt, nextPt ).angle();
377+
}
378+
else if ( i == points.count() - 1 )
379+
{
380+
const QPointF& prevPt = points[i-1];
381+
if ( pt == prevPt )
382+
continue;
383+
angle = MyLine( prevPt, pt ).angle();
384+
}
385+
else
386+
{
387+
const QPointF& prevPt = points[i-1];
388+
const QPointF& nextPt = points[i+1];
389+
if ( prevPt == pt || nextPt == pt )
390+
continue;
391+
392+
// calc average angle between the previous and next point
393+
double a1 = MyLine( prevPt, pt ).angle();
394+
double a2 = MyLine( pt, nextPt ).angle();
395+
double unitX = cos( a1 ) + cos( a2 ), unitY = sin( a1 ) + sin( a2 );
396+
angle = atan2( unitY, unitX );
397+
}
398+
mMarker->setAngle( angle * 180 / M_PI );
399+
}
400+
401+
mMarker->renderPoint( points.at( i ), rc, -1, context.selected() );
402+
}
403+
404+
// restore original rotation
405+
mMarker->setAngle( origAngle );
406+
}
407+
347408
QgsStringMap QgsMarkerLineSymbolLayerV2::properties() const
348409
{
349410
QgsStringMap map;
350411
map["rotate"] = ( mRotateMarker ? "1" : "0" );
351412
map["interval"] = QString::number( mInterval );
352413
map["offset"] = QString::number( mOffset );
414+
map["placement"] = ( mPlacement == Vertex ? "vertex" : "interval" );
353415
return map;
354416
}
355417

@@ -377,6 +439,7 @@ QgsSymbolLayerV2* QgsMarkerLineSymbolLayerV2::clone() const
377439
QgsMarkerLineSymbolLayerV2* x = new QgsMarkerLineSymbolLayerV2( mRotateMarker, mInterval );
378440
x->setSubSymbol( mMarker->clone() );
379441
x->setOffset( mOffset );
442+
x->setPlacement( mPlacement );
380443
return x;
381444
}
382445

src/core/symbology-ng/qgslinesymbollayerv2.h

+12-1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ class CORE_EXPORT QgsMarkerLineSymbolLayerV2 : public QgsLineSymbolLayerV2
8585

8686
~QgsMarkerLineSymbolLayerV2();
8787

88+
enum Placement
89+
{
90+
Interval,
91+
Vertex
92+
};
93+
8894
// static stuff
8995

9096
static QgsSymbolLayerV2* create( const QgsStringMap& properties = QgsStringMap() );
@@ -122,14 +128,19 @@ class CORE_EXPORT QgsMarkerLineSymbolLayerV2 : public QgsLineSymbolLayerV2
122128
double offset() const { return mOffset; }
123129
void setOffset( double offset ) { mOffset = offset; }
124130

131+
Placement placement() const { return mPlacement; }
132+
void setPlacement( Placement p ) { mPlacement = p; }
133+
125134
protected:
126135

127-
void renderPolylineNoOffset( const QPolygonF& points, QgsSymbolV2RenderContext& context );
136+
void renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context );
137+
void renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context );
128138

129139
bool mRotateMarker;
130140
double mInterval;
131141
QgsMarkerSymbolV2* mMarker;
132142
double mOffset;
143+
Placement mPlacement;
133144
};
134145

135146
/////////

src/gui/symbology-ng/qgssymbollayerv2widget.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ QgsMarkerLineSymbolLayerV2Widget::QgsMarkerLineSymbolLayerV2Widget( QWidget* par
359359
connect( btnChangeMarker, SIGNAL( clicked() ), this, SLOT( setMarker() ) );
360360
connect( chkRotateMarker, SIGNAL( clicked() ), this, SLOT( setRotate() ) );
361361
connect( spinOffset, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
362+
connect( radInterval, SIGNAL( clicked() ), this, SLOT( setPlacement() ) );
363+
connect( radVertex, SIGNAL( clicked() ), this, SLOT( setPlacement() ) );
362364
}
363365

364366
void QgsMarkerLineSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
@@ -373,7 +375,12 @@ void QgsMarkerLineSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
373375
spinInterval->setValue( mLayer->interval() );
374376
chkRotateMarker->setChecked( mLayer->rotateMarker() );
375377
spinOffset->setValue( mLayer->offset() );
378+
if ( mLayer->placement() == QgsMarkerLineSymbolLayerV2::Interval )
379+
radInterval->setChecked( true );
380+
else
381+
radVertex->setChecked( true );
376382
updateMarker();
383+
setPlacement(); // update gui
377384
}
378385

379386
QgsSymbolLayerV2* QgsMarkerLineSymbolLayerV2Widget::symbolLayer()
@@ -416,6 +423,13 @@ void QgsMarkerLineSymbolLayerV2Widget::updateMarker()
416423
btnChangeMarker->setIcon( icon );
417424
}
418425

426+
void QgsMarkerLineSymbolLayerV2Widget::setPlacement()
427+
{
428+
bool interval = radInterval->isChecked();
429+
mLayer->setPlacement( interval ? QgsMarkerLineSymbolLayerV2::Interval : QgsMarkerLineSymbolLayerV2::Vertex );
430+
spinInterval->setEnabled( interval );
431+
emit changed();
432+
}
419433

420434
///////////
421435

src/gui/symbology-ng/qgssymbollayerv2widget.h

+1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ class GUI_EXPORT QgsMarkerLineSymbolLayerV2Widget : public QgsSymbolLayerV2Widge
145145
void setMarker();
146146
void setRotate();
147147
void setOffset();
148+
void setPlacement();
148149

149150
protected:
150151

src/ui/symbollayer/widget_markerline.ui

+52-31
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>360</width>
10-
<height>192</height>
9+
<width>352</width>
10+
<height>232</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
1414
<string>Form</string>
1515
</property>
16-
<layout class="QVBoxLayout">
16+
<layout class="QVBoxLayout" name="verticalLayout">
1717
<item>
18-
<layout class="QGridLayout">
18+
<layout class="QGridLayout" name="gridLayout">
1919
<item row="0" column="0">
2020
<widget class="QLabel" name="label">
2121
<property name="text">
@@ -30,44 +30,58 @@
3030
</property>
3131
</widget>
3232
</item>
33-
<item row="0" column="2" rowspan="4">
34-
<spacer>
35-
<property name="orientation">
36-
<enum>Qt::Horizontal</enum>
33+
<item row="1" column="0" colspan="2">
34+
<widget class="QLabel" name="label_2">
35+
<property name="text">
36+
<string>Marker placement</string>
3737
</property>
38-
<property name="sizeType">
39-
<enum>QSizePolicy::Preferred</enum>
38+
</widget>
39+
</item>
40+
<item row="2" column="0">
41+
<widget class="QRadioButton" name="radInterval">
42+
<property name="text">
43+
<string>with interval</string>
4044
</property>
41-
<property name="sizeHint" stdset="0">
42-
<size>
43-
<width>40</width>
44-
<height>20</height>
45-
</size>
45+
<property name="checked">
46+
<bool>true</bool>
4647
</property>
47-
</spacer>
48+
</widget>
4849
</item>
49-
<item row="1" column="0">
50-
<widget class="QLabel" name="label_2">
50+
<item row="2" column="1">
51+
<widget class="QDoubleSpinBox" name="spinInterval">
52+
<property name="decimals">
53+
<number>2</number>
54+
</property>
55+
<property name="maximum">
56+
<double>100000.000000000000000</double>
57+
</property>
58+
<property name="value">
59+
<double>1.000000000000000</double>
60+
</property>
61+
</widget>
62+
</item>
63+
<item row="3" column="0" colspan="2">
64+
<widget class="QRadioButton" name="radVertex">
5165
<property name="text">
52-
<string>Marker interval</string>
66+
<string>on every vertex</string>
5367
</property>
5468
</widget>
5569
</item>
56-
<item row="2" column="0" colspan="2">
70+
<item row="4" column="0" colspan="2">
5771
<widget class="QCheckBox" name="chkRotateMarker">
5872
<property name="text">
5973
<string>Rotate marker</string>
6074
</property>
6175
</widget>
6276
</item>
63-
<item row="3" column="0">
77+
<item row="5" column="0">
6478
<widget class="QLabel" name="label_3">
6579
<property name="text">
6680
<string>Line offset</string>
6781
</property>
6882
</widget>
6983
</item>
70-
<item row="3" column="1">
84+
<item row="5" column="1">
7185
<widget class="QDoubleSpinBox" name="spinOffset">
7286
<property name="decimals">
7387
<number>2</number>
@@ -80,18 +94,21 @@
8094
</property>
8195
</widget>
8296
</item>
83-
<item row="1" column="1">
84-
<widget class="QDoubleSpinBox" name="spinInterval">
85-
<property name="decimals">
86-
<number>2</number>
97+
<item row="0" column="2" rowspan="6">
98+
<spacer>
99+
<property name="orientation">
100+
<enum>Qt::Horizontal</enum>
87101
</property>
88-
<property name="maximum">
89-
<double>100000.000000000000000</double>
102+
<property name="sizeType">
103+
<enum>QSizePolicy::Preferred</enum>
90104
</property>
91-
<property name="value">
92-
<double>1.000000000000000</double>
105+
<property name="sizeHint" stdset="0">
106+
<size>
107+
<width>110</width>
108+
<height>20</height>
109+
</size>
93110
</property>
94-
</widget>
111+
</spacer>
95112
</item>
96113
</layout>
97114
</item>
@@ -112,7 +129,11 @@
112129
</widget>
113130
<tabstops>
114131
<tabstop>btnChangeMarker</tabstop>
132+
<tabstop>radInterval</tabstop>
115133
<tabstop>spinInterval</tabstop>
134+
<tabstop>radVertex</tabstop>
135+
<tabstop>chkRotateMarker</tabstop>
136+
<tabstop>spinOffset</tabstop>
116137
</tabstops>
117138
<resources/>
118139
<connections/>

0 commit comments

Comments
 (0)