From 1ed52037ff1bfc706dbf896fb9da2acfbea0fa44 Mon Sep 17 00:00:00 2001 From: wonder Date: Sun, 28 Nov 2010 20:14:36 +0000 Subject: [PATCH] [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/qgis@14779 c8812cc2-4d05-0410-92ff-de0c093fc19c --- .../symbology-ng/qgslinesymbollayerv2.cpp | 69 ++++++++++++++- src/core/symbology-ng/qgslinesymbollayerv2.h | 13 ++- .../symbology-ng/qgssymbollayerv2widget.cpp | 14 ++++ src/gui/symbology-ng/qgssymbollayerv2widget.h | 1 + src/ui/symbollayer/widget_markerline.ui | 83 ++++++++++++------- 5 files changed, 145 insertions(+), 35 deletions(-) diff --git a/src/core/symbology-ng/qgslinesymbollayerv2.cpp b/src/core/symbology-ng/qgslinesymbollayerv2.cpp index 4b32d0ccda13..7bdd6e307bc5 100644 --- a/src/core/symbology-ng/qgslinesymbollayerv2.cpp +++ b/src/core/symbology-ng/qgslinesymbollayerv2.cpp @@ -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; } diff --git a/src/core/symbology-ng/qgslinesymbollayerv2.h b/src/core/symbology-ng/qgslinesymbollayerv2.h index bf30564f0131..a0354b02644c 100644 --- a/src/core/symbology-ng/qgslinesymbollayerv2.h +++ b/src/core/symbology-ng/qgslinesymbollayerv2.h @@ -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; }; ///////// diff --git a/src/gui/symbology-ng/qgssymbollayerv2widget.cpp b/src/gui/symbology-ng/qgssymbollayerv2widget.cpp index 712de288a435..f0a6afa795c6 100644 --- a/src/gui/symbology-ng/qgssymbollayerv2widget.cpp +++ b/src/gui/symbology-ng/qgssymbollayerv2widget.cpp @@ -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(); +} /////////// diff --git a/src/gui/symbology-ng/qgssymbollayerv2widget.h b/src/gui/symbology-ng/qgssymbollayerv2widget.h index f545db68b268..eedbfd6626f4 100644 --- a/src/gui/symbology-ng/qgssymbollayerv2widget.h +++ b/src/gui/symbology-ng/qgssymbollayerv2widget.h @@ -145,6 +145,7 @@ class GUI_EXPORT QgsMarkerLineSymbolLayerV2Widget : public QgsSymbolLayerV2Widge void setMarker(); void setRotate(); void setOffset(); + void setPlacement(); protected: diff --git a/src/ui/symbollayer/widget_markerline.ui b/src/ui/symbollayer/widget_markerline.ui index 00a5738f14f5..cfddf2daa9c3 100644 --- a/src/ui/symbollayer/widget_markerline.ui +++ b/src/ui/symbollayer/widget_markerline.ui @@ -6,16 +6,16 @@ 0 0 - 360 - 192 + 352 + 232 Form - + - + @@ -30,44 +30,58 @@ - - - - Qt::Horizontal + + + + Marker placement - - QSizePolicy::Preferred + + + + + + with interval - - - 40 - 20 - + + true - + - - + + + + 2 + + + 100000.000000000000000 + + + 1.000000000000000 + + + + + - Marker interval + on every vertex - + Rotate marker - + Line offset - + 2 @@ -80,18 +94,21 @@ - - - - 2 + + + + Qt::Horizontal - - 100000.000000000000000 + + QSizePolicy::Preferred - - 1.000000000000000 + + + 110 + 20 + - + @@ -112,7 +129,11 @@ btnChangeMarker + radInterval spinInterval + radVertex + chkRotateMarker + spinOffset