Skip to content
Permalink
Browse files

[FEATURE] Allow the marker line symbol layer draw markers on each ver…

…tex.

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
  • Loading branch information
wonder
wonder committed Nov 28, 2010
1 parent e7428cd commit 89e0a9466b72a96b9f38510af48fcb3d5ea1a8d0
@@ -215,6 +215,7 @@ QgsMarkerLineSymbolLayerV2::QgsMarkerLineSymbolLayerV2( bool rotateMarker, doubl
mInterval = interval;
mMarker = NULL;
mOffset = 0;
mPlacement = Interval;

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

@@ -276,16 +279,22 @@ void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSym
{
if ( mOffset == 0 )
{
renderPolylineNoOffset( points, context );
if ( mPlacement == Vertex )
renderPolylineVertex( points, context );
else
renderPolylineInterval( points, context );
}
else
{
QPolygonF points2 = ::offsetLine( points, context.outputLineWidth( mOffset ) );
renderPolylineNoOffset( points2, context );
if ( mPlacement == Vertex )
renderPolylineVertex( points2, context );
else
renderPolylineInterval( points2, context );
}
}

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

}

void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context )
{
QPointF lastPt = points[0];
QgsRenderContext& rc = context.renderContext();

double origAngle = mMarker->angle();
double angle;

for ( int i = 0; i < points.count(); ++i )
{
const QPointF& pt = points[i];

// rotate marker (if desired)
if ( mRotateMarker )
{
if ( i == 0 )
{
const QPointF& nextPt = points[i+1];
if ( pt == nextPt )
continue;
angle = MyLine( pt, nextPt ).angle();
}
else if ( i == points.count() - 1 )
{
const QPointF& prevPt = points[i-1];
if ( pt == prevPt )
continue;
angle = MyLine( prevPt, pt ).angle();
}
else
{
const QPointF& prevPt = points[i-1];
const QPointF& nextPt = points[i+1];
if ( prevPt == pt || nextPt == pt )
continue;

// calc average angle between the previous and next point
double a1 = MyLine( prevPt, pt ).angle();
double a2 = MyLine( pt, nextPt ).angle();
double unitX = cos( a1 ) + cos( a2 ), unitY = sin( a1 ) + sin( a2 );
angle = atan2( unitY, unitX );
}
mMarker->setAngle( angle * 180 / M_PI );
}

mMarker->renderPoint( points.at( i ), rc, -1, context.selected() );
}

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

QgsStringMap QgsMarkerLineSymbolLayerV2::properties() const
{
QgsStringMap map;
map["rotate"] = ( mRotateMarker ? "1" : "0" );
map["interval"] = QString::number( mInterval );
map["offset"] = QString::number( mOffset );
map["placement"] = ( mPlacement == Vertex ? "vertex" : "interval" );
return map;
}

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

@@ -85,6 +85,12 @@ class CORE_EXPORT QgsMarkerLineSymbolLayerV2 : public QgsLineSymbolLayerV2

~QgsMarkerLineSymbolLayerV2();

enum Placement
{
Interval,
Vertex
};

// static stuff

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

Placement placement() const { return mPlacement; }
void setPlacement( Placement p ) { mPlacement = p; }

protected:

void renderPolylineNoOffset( const QPolygonF& points, QgsSymbolV2RenderContext& context );
void renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context );
void renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context );

bool mRotateMarker;
double mInterval;
QgsMarkerSymbolV2* mMarker;
double mOffset;
Placement mPlacement;
};

/////////
@@ -359,6 +359,8 @@ QgsMarkerLineSymbolLayerV2Widget::QgsMarkerLineSymbolLayerV2Widget( QWidget* par
connect( btnChangeMarker, SIGNAL( clicked() ), this, SLOT( setMarker() ) );
connect( chkRotateMarker, SIGNAL( clicked() ), this, SLOT( setRotate() ) );
connect( spinOffset, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
connect( radInterval, SIGNAL( clicked() ), this, SLOT( setPlacement() ) );
connect( radVertex, SIGNAL( clicked() ), this, SLOT( setPlacement() ) );
}

void QgsMarkerLineSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
@@ -373,7 +375,12 @@ void QgsMarkerLineSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
spinInterval->setValue( mLayer->interval() );
chkRotateMarker->setChecked( mLayer->rotateMarker() );
spinOffset->setValue( mLayer->offset() );
if ( mLayer->placement() == QgsMarkerLineSymbolLayerV2::Interval )
radInterval->setChecked( true );
else
radVertex->setChecked( true );
updateMarker();
setPlacement(); // update gui
}

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

void QgsMarkerLineSymbolLayerV2Widget::setPlacement()
{
bool interval = radInterval->isChecked();
mLayer->setPlacement( interval ? QgsMarkerLineSymbolLayerV2::Interval : QgsMarkerLineSymbolLayerV2::Vertex );
spinInterval->setEnabled( interval );
emit changed();
}

///////////

@@ -145,6 +145,7 @@ class GUI_EXPORT QgsMarkerLineSymbolLayerV2Widget : public QgsSymbolLayerV2Widge
void setMarker();
void setRotate();
void setOffset();
void setPlacement();

protected:

@@ -6,16 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>192</height>
<width>352</width>
<height>232</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
@@ -30,44 +30,58 @@
</property>
</widget>
</item>
<item row="0" column="2" rowspan="4">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Marker placement</string>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="radInterval">
<property name="text">
<string>with interval</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
<property name="checked">
<bool>true</bool>
</property>
</spacer>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="spinInterval">
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>100000.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QRadioButton" name="radVertex">
<property name="text">
<string>Marker interval</string>
<string>on every vertex</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="chkRotateMarker">
<property name="text">
<string>Rotate marker</string>
</property>
</widget>
</item>
<item row="3" column="0">
<item row="5" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Line offset</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="spinOffset">
<property name="decimals">
<number>2</number>
@@ -80,18 +94,21 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="spinInterval">
<property name="decimals">
<number>2</number>
<item row="0" column="2" rowspan="6">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="maximum">
<double>100000.000000000000000</double>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="value">
<double>1.000000000000000</double>
<property name="sizeHint" stdset="0">
<size>
<width>110</width>
<height>20</height>
</size>
</property>
</widget>
</spacer>
</item>
</layout>
</item>
@@ -112,7 +129,11 @@
</widget>
<tabstops>
<tabstop>btnChangeMarker</tabstop>
<tabstop>radInterval</tabstop>
<tabstop>spinInterval</tabstop>
<tabstop>radVertex</tabstop>
<tabstop>chkRotateMarker</tabstop>
<tabstop>spinOffset</tabstop>
</tabstops>
<resources/>
<connections/>

0 comments on commit 89e0a94

Please sign in to comment.
You can’t perform that action at this time.