Quantum GIS API Documentation  1.7.4
src/core/symbology-ng/qgslinesymbollayerv2.cpp
Go to the documentation of this file.
00001 
00002 #include "qgslinesymbollayerv2.h"
00003 #include "qgssymbollayerv2utils.h"
00004 
00005 #include "qgsrendercontext.h"
00006 
00007 #include <QPainter>
00008 
00009 #include <cmath>
00010 
00011 QgsSimpleLineSymbolLayerV2::QgsSimpleLineSymbolLayerV2( QColor color, double width, Qt::PenStyle penStyle )
00012     : mPenStyle( penStyle ), mPenJoinStyle( DEFAULT_SIMPLELINE_JOINSTYLE ), mPenCapStyle( DEFAULT_SIMPLELINE_CAPSTYLE ), mOffset( 0 ), mUseCustomDashPattern( false )
00013 {
00014   mColor = color;
00015   mWidth = width;
00016   mCustomDashVector << 5 << 2;
00017 }
00018 
00019 
00020 QgsSymbolLayerV2* QgsSimpleLineSymbolLayerV2::create( const QgsStringMap& props )
00021 {
00022   QColor color = DEFAULT_SIMPLELINE_COLOR;
00023   double width = DEFAULT_SIMPLELINE_WIDTH;
00024   Qt::PenStyle penStyle = DEFAULT_SIMPLELINE_PENSTYLE;
00025 
00026   if ( props.contains( "color" ) )
00027     color = QgsSymbolLayerV2Utils::decodeColor( props["color"] );
00028   if ( props.contains( "width" ) )
00029     width = props["width"].toDouble();
00030   if ( props.contains( "penstyle" ) )
00031     penStyle = QgsSymbolLayerV2Utils::decodePenStyle( props["penstyle"] );
00032 
00033 
00034   QgsSimpleLineSymbolLayerV2* l = new QgsSimpleLineSymbolLayerV2( color, width, penStyle );
00035   if ( props.contains( "offset" ) )
00036     l->setOffset( props["offset"].toDouble() );
00037   if ( props.contains( "joinstyle" ) )
00038     l->setPenJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( props["joinstyle"] ) );
00039   if ( props.contains( "capstyle" ) )
00040     l->setPenCapStyle( QgsSymbolLayerV2Utils::decodePenCapStyle( props["capstyle"] ) );
00041 
00042   if ( props.contains( "use_custom_dash" ) )
00043   {
00044     l->setUseCustomDashPattern( props["use_custom_dash"].toInt() );
00045   }
00046   if ( props.contains( "customdash" ) )
00047   {
00048     l->setCustomDashVector( QgsSymbolLayerV2Utils::decodeRealVector( props["customdash"] ) );
00049   }
00050   return l;
00051 }
00052 
00053 
00054 QString QgsSimpleLineSymbolLayerV2::layerType() const
00055 {
00056   return "SimpleLine";
00057 }
00058 
00059 void QgsSimpleLineSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
00060 {
00061   QColor penColor = mColor;
00062   penColor.setAlphaF( context.alpha() );
00063   mPen.setColor( penColor );
00064   double scaledWidth = context.outputLineWidth( mWidth );
00065   mPen.setWidthF( scaledWidth );
00066   if ( mUseCustomDashPattern && scaledWidth != 0 )
00067   {
00068     mPen.setStyle( Qt::CustomDashLine );
00069 
00070     //scale pattern vector
00071     QVector<qreal> scaledVector;
00072     QVector<qreal>::const_iterator it = mCustomDashVector.constBegin();
00073     for ( ; it != mCustomDashVector.constEnd(); ++it )
00074     {
00075       //the dash is specified in terms of pen widths, therefore the division
00076       scaledVector << context.outputLineWidth(( *it ) / scaledWidth );
00077     }
00078     mPen.setDashPattern( scaledVector );
00079   }
00080   else
00081   {
00082     mPen.setStyle( mPenStyle );
00083   }
00084   mPen.setJoinStyle( mPenJoinStyle );
00085   mPen.setCapStyle( mPenCapStyle );
00086 
00087   mSelPen = mPen;
00088   QColor selColor = context.selectionColor();
00089   if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() );
00090   mSelPen.setColor( selColor );
00091 }
00092 
00093 void QgsSimpleLineSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
00094 {
00095 }
00096 
00097 void QgsSimpleLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context )
00098 {
00099   QPainter* p = context.renderContext().painter();
00100   if ( !p )
00101   {
00102     return;
00103   }
00104 
00105   if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale )
00106   {
00107     double scaledWidth = context.outputLineWidth( mWidth );
00108     mPen.setWidthF( scaledWidth );
00109     mSelPen.setWidthF( scaledWidth );
00110   }
00111 
00112   p->setPen( context.selected() ? mSelPen : mPen );
00113   if ( mOffset == 0 )
00114   {
00115     p->drawPolyline( points );
00116   }
00117   else
00118   {
00119     double scaledOffset = context.outputLineWidth( mOffset );
00120     p->drawPolyline( ::offsetLine( points, scaledOffset ) );
00121   }
00122 }
00123 
00124 QgsStringMap QgsSimpleLineSymbolLayerV2::properties() const
00125 {
00126   QgsStringMap map;
00127   map["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
00128   map["width"] = QString::number( mWidth );
00129   map["penstyle"] = QgsSymbolLayerV2Utils::encodePenStyle( mPenStyle );
00130   map["joinstyle"] = QgsSymbolLayerV2Utils::encodePenJoinStyle( mPenJoinStyle );
00131   map["capstyle"] = QgsSymbolLayerV2Utils::encodePenCapStyle( mPenCapStyle );
00132   map["offset"] = QString::number( mOffset );
00133   map["use_custom_dash"] = ( mUseCustomDashPattern ? "1" : "0" );
00134   map["customdash"] = QgsSymbolLayerV2Utils::encodeRealVector( mCustomDashVector );
00135   return map;
00136 }
00137 
00138 QgsSymbolLayerV2* QgsSimpleLineSymbolLayerV2::clone() const
00139 {
00140   QgsSimpleLineSymbolLayerV2* l = new QgsSimpleLineSymbolLayerV2( mColor, mWidth, mPenStyle );
00141   l->setOffset( mOffset );
00142   l->setPenJoinStyle( mPenJoinStyle );
00143   l->setPenCapStyle( mPenCapStyle );
00144   l->setUseCustomDashPattern( mUseCustomDashPattern );
00145   l->setCustomDashVector( mCustomDashVector );
00146   return l;
00147 }
00148 
00149 
00151 
00152 
00153 class MyLine
00154 {
00155   public:
00156     MyLine( QPointF p1, QPointF p2 ) : mVertical( false ), mIncreasing( false ), mT( 0.0 ), mLength( 0.0 )
00157     {
00158       if ( p1 == p2 )
00159         return; // invalid
00160 
00161       // tangent and direction
00162       if ( p1.x() == p2.x() )
00163       {
00164         // vertical line - tangent undefined
00165         mVertical = true;
00166         mIncreasing = ( p2.y() > p1.y() );
00167       }
00168       else
00169       {
00170         mVertical = false;
00171         mT = float( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
00172         mIncreasing = ( p2.x() > p1.x() );
00173       }
00174 
00175       // length
00176       double x = ( p2.x() - p1.x() );
00177       double y = ( p2.y() - p1.y() );
00178       mLength = sqrt( x * x + y * y );
00179     }
00180 
00181     // return angle in radians
00182     double angle()
00183     {
00184       double a = ( mVertical ? M_PI / 2 : atan( mT ) );
00185 
00186       if ( !mIncreasing )
00187         a += M_PI;
00188       return a;
00189     }
00190 
00191     // return difference for x,y when going along the line with specified interval
00192     QPointF diffForInterval( double interval )
00193     {
00194       if ( mVertical )
00195         return ( mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
00196 
00197       double alpha = atan( mT );
00198       double dx = cos( alpha ) * interval;
00199       double dy = sin( alpha ) * interval;
00200       return ( mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
00201     }
00202 
00203     double length() { return mLength; }
00204 
00205   protected:
00206     bool mVertical;
00207     bool mIncreasing;
00208     double mT;
00209     double mLength;
00210 };
00211 
00212 
00213 QgsMarkerLineSymbolLayerV2::QgsMarkerLineSymbolLayerV2( bool rotateMarker, double interval )
00214 {
00215   mRotateMarker = rotateMarker;
00216   mInterval = interval;
00217   mMarker = NULL;
00218   mOffset = 0;
00219   mPlacement = Interval;
00220 
00221   setSubSymbol( new QgsMarkerSymbolV2() );
00222 }
00223 
00224 QgsMarkerLineSymbolLayerV2::~QgsMarkerLineSymbolLayerV2()
00225 {
00226   delete mMarker;
00227 }
00228 
00229 QgsSymbolLayerV2* QgsMarkerLineSymbolLayerV2::create( const QgsStringMap& props )
00230 {
00231   bool rotate = DEFAULT_MARKERLINE_ROTATE;
00232   double interval = DEFAULT_MARKERLINE_INTERVAL;
00233 
00234   if ( props.contains( "interval" ) )
00235     interval = props["interval"].toDouble();
00236   if ( props.contains( "rotate" ) )
00237     rotate = ( props["rotate"] == "1" );
00238 
00239   QgsMarkerLineSymbolLayerV2* x = new QgsMarkerLineSymbolLayerV2( rotate, interval );
00240   if ( props.contains( "offset" ) )
00241   {
00242     x->setOffset( props["offset"].toDouble() );
00243   }
00244 
00245   if ( props.contains( "placement" ) )
00246   {
00247     if ( props["placement"] == "vertex" )
00248       x->setPlacement( Vertex );
00249     else if ( props["placement"] == "lastvertex" )
00250       x->setPlacement( LastVertex );
00251     else if ( props["placement"] == "firstvertex" )
00252       x->setPlacement( FirstVertex );
00253     else if ( props["placement"] == "centralpoint" )
00254       x->setPlacement( CentralPoint );
00255     else
00256       x->setPlacement( Interval );
00257   }
00258   return x;
00259 }
00260 
00261 QString QgsMarkerLineSymbolLayerV2::layerType() const
00262 {
00263   return "MarkerLine";
00264 }
00265 
00266 void QgsMarkerLineSymbolLayerV2::setColor( const QColor& color )
00267 {
00268   mMarker->setColor( color );
00269   mColor = color;
00270 }
00271 
00272 void QgsMarkerLineSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
00273 {
00274   mMarker->setAlpha( context.alpha() );
00275   mMarker->setOutputUnit( context.outputUnit() );
00276 
00277   // if being rotated, it gets initialized with every line segment
00278   int hints = 0;
00279   if ( mRotateMarker )
00280     hints |= QgsSymbolV2::DataDefinedRotation;
00281   if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale )
00282     hints |= QgsSymbolV2::DataDefinedSizeScale;
00283   mMarker->setRenderHints( hints );
00284 
00285   mMarker->startRender( context.renderContext() );
00286 }
00287 
00288 void QgsMarkerLineSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
00289 {
00290   mMarker->stopRender( context.renderContext() );
00291 }
00292 
00293 void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context )
00294 {
00295   if ( mOffset == 0 )
00296   {
00297     if ( mPlacement == Interval )
00298       renderPolylineInterval( points, context );
00299     else if ( mPlacement == CentralPoint )
00300       renderPolylineCentral( points, context );
00301     else
00302       renderPolylineVertex( points, context );
00303   }
00304   else
00305   {
00306     QPolygonF points2 = ::offsetLine( points, context.outputLineWidth( mOffset ) );
00307     if ( mPlacement == Interval )
00308       renderPolylineInterval( points2, context );
00309     else if ( mPlacement == CentralPoint )
00310       renderPolylineCentral( points2, context );
00311     else
00312       renderPolylineVertex( points2, context );
00313   }
00314 }
00315 
00316 void QgsMarkerLineSymbolLayerV2::renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context )
00317 {
00318   if ( points.isEmpty() )
00319     return;
00320 
00321   QPointF lastPt = points[0];
00322   double lengthLeft = 0; // how much is left until next marker
00323   bool first = true;
00324   double origAngle = mMarker->angle();
00325 
00326   double painterUnitInterval = context.outputLineWidth( mInterval > 0 ? mInterval : 0.1 );
00327 
00328   QgsRenderContext& rc = context.renderContext();
00329 
00330   for ( int i = 1; i < points.count(); ++i )
00331   {
00332     const QPointF& pt = points[i];
00333 
00334     if ( lastPt == pt ) // must not be equal!
00335       continue;
00336 
00337     // for each line, find out dx and dy, and length
00338     MyLine l( lastPt, pt );
00339     QPointF diff = l.diffForInterval( painterUnitInterval );
00340 
00341     // if there's some length left from previous line
00342     // use only the rest for the first point in new line segment
00343     double c = 1 - lengthLeft / painterUnitInterval;
00344 
00345     lengthLeft += l.length();
00346 
00347     // rotate marker (if desired)
00348     if ( mRotateMarker )
00349     {
00350       mMarker->setAngle( origAngle + ( l.angle() * 180 / M_PI ) );
00351     }
00352 
00353     // draw first marker
00354     if ( first )
00355     {
00356       mMarker->renderPoint( lastPt, rc, -1, context.selected() );
00357       first = false;
00358     }
00359 
00360     // while we're not at the end of line segment, draw!
00361     while ( lengthLeft > painterUnitInterval )
00362     {
00363       // "c" is 1 for regular point or in interval (0,1] for begin of line segment
00364       lastPt += c * diff;
00365       lengthLeft -= painterUnitInterval;
00366       mMarker->renderPoint( lastPt, rc, -1, context.selected() );
00367       c = 1; // reset c (if wasn't 1 already)
00368     }
00369 
00370     lastPt = pt;
00371   }
00372 
00373   // restore original rotation
00374   mMarker->setAngle( origAngle );
00375 
00376 }
00377 
00378 static double _averageAngle( const QPointF& prevPt, const QPointF& pt, const QPointF& nextPt )
00379 {
00380   // calc average angle between the previous and next point
00381   double a1 = MyLine( prevPt, pt ).angle();
00382   double a2 = MyLine( pt, nextPt ).angle();
00383   double unitX = cos( a1 ) + cos( a2 ), unitY = sin( a1 ) + sin( a2 );
00384 
00385   return atan2( unitY, unitX );
00386 }
00387 
00388 void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context )
00389 {
00390   if ( points.isEmpty() )
00391     return;
00392 
00393   QgsRenderContext& rc = context.renderContext();
00394 
00395   double origAngle = mMarker->angle();
00396   double angle;
00397   int i, maxCount;
00398   bool isRing = false;
00399 
00400   if ( mPlacement == FirstVertex )
00401   {
00402     i = 0;
00403     maxCount = 1;
00404   }
00405   else if ( mPlacement == LastVertex )
00406   {
00407     i = points.count() - 1;
00408     maxCount = points.count();
00409   }
00410   else
00411   {
00412     i = 0;
00413     maxCount = points.count();
00414     if ( points.first() == points.last() )
00415       isRing = true;
00416   }
00417 
00418   for ( ; i < maxCount; ++i )
00419   {
00420     const QPointF& pt = points[i];
00421 
00422     // rotate marker (if desired)
00423     if ( mRotateMarker )
00424     {
00425       if ( i == 0 )
00426       {
00427         if ( !isRing )
00428         {
00429           // use first segment's angle
00430           const QPointF& nextPt = points[i+1];
00431           if ( pt == nextPt )
00432             continue;
00433           angle = MyLine( pt, nextPt ).angle();
00434         }
00435         else
00436         {
00437           // closed ring: use average angle between first and last segment
00438           const QPointF& prevPt = points[points.count() - 2];
00439           const QPointF& nextPt = points[1];
00440           if ( prevPt == pt || nextPt == pt )
00441             continue;
00442 
00443           angle = _averageAngle( prevPt, pt, nextPt );
00444         }
00445       }
00446       else if ( i == points.count() - 1 )
00447       {
00448         if ( !isRing )
00449         {
00450           // use last segment's angle
00451           const QPointF& prevPt = points[i-1];
00452           if ( pt == prevPt )
00453             continue;
00454           angle = MyLine( prevPt, pt ).angle();
00455         }
00456         else
00457         {
00458           // don't draw the last marker - it has been drawn already
00459           continue;
00460         }
00461       }
00462       else
00463       {
00464         // use average angle
00465         const QPointF& prevPt = points[i-1];
00466         const QPointF& nextPt = points[i+1];
00467         if ( prevPt == pt || nextPt == pt )
00468           continue;
00469 
00470         angle = _averageAngle( prevPt, pt, nextPt );
00471       }
00472       mMarker->setAngle( origAngle + angle * 180 / M_PI );
00473     }
00474 
00475     mMarker->renderPoint( points.at( i ), rc, -1, context.selected() );
00476   }
00477 
00478   // restore original rotation
00479   mMarker->setAngle( origAngle );
00480 }
00481 
00482 void QgsMarkerLineSymbolLayerV2::renderPolylineCentral( const QPolygonF& points, QgsSymbolV2RenderContext& context )
00483 {
00484   // calc length
00485   qreal length = 0;
00486   QPolygonF::const_iterator it = points.constBegin();
00487   QPointF last = *it;
00488   for ( ++it; it != points.constEnd(); ++it )
00489   {
00490     length += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) +
00491                    ( last.y() - it->y() ) * ( last.y() - it->y() ) );
00492     last = *it;
00493   }
00494 
00495   // find the segment where the central point lies
00496   it = points.constBegin();
00497   last = *it;
00498   qreal last_at = 0, next_at = 0;
00499   QPointF next;
00500   int segment = 0;
00501   for ( ++it; it != points.constEnd(); ++it )
00502   {
00503     next = *it;
00504     next_at += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) +
00505                     ( last.y() - it->y() ) * ( last.y() - it->y() ) );
00506     if ( next_at >= length / 2 )
00507       break; // we have reached the center
00508     last = *it;
00509     last_at = next_at;
00510     segment++;
00511   }
00512 
00513   // find out the central point on segment
00514   MyLine l( last, next ); // for line angle
00515   qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
00516   QPointF pt = last + ( next - last ) * k;
00517 
00518   // draw the marker
00519   double origAngle = mMarker->angle();
00520   if ( mRotateMarker )
00521     mMarker->setAngle( origAngle + l.angle() * 180 / M_PI );
00522   mMarker->renderPoint( pt, context.renderContext(), -1, context.selected() );
00523   if ( mRotateMarker )
00524     mMarker->setAngle( origAngle );
00525 }
00526 
00527 
00528 QgsStringMap QgsMarkerLineSymbolLayerV2::properties() const
00529 {
00530   QgsStringMap map;
00531   map["rotate"] = ( mRotateMarker ? "1" : "0" );
00532   map["interval"] = QString::number( mInterval );
00533   map["offset"] = QString::number( mOffset );
00534   if ( mPlacement == Vertex )
00535     map["placement"] = "vertex";
00536   else if ( mPlacement == LastVertex )
00537     map["placement"] = "lastvertex";
00538   else if ( mPlacement == FirstVertex )
00539     map["placement"] = "firstvertex";
00540   else if ( mPlacement == CentralPoint )
00541     map["placement"] = "centralpoint";
00542   else
00543     map["placement"] = "interval";
00544   return map;
00545 }
00546 
00547 QgsSymbolV2* QgsMarkerLineSymbolLayerV2::subSymbol()
00548 {
00549   return mMarker;
00550 }
00551 
00552 bool QgsMarkerLineSymbolLayerV2::setSubSymbol( QgsSymbolV2* symbol )
00553 {
00554   if ( symbol == NULL || symbol->type() != QgsSymbolV2::Marker )
00555   {
00556     delete symbol;
00557     return false;
00558   }
00559 
00560   delete mMarker;
00561   mMarker = static_cast<QgsMarkerSymbolV2*>( symbol );
00562   mColor = mMarker->color();
00563   return true;
00564 }
00565 
00566 QgsSymbolLayerV2* QgsMarkerLineSymbolLayerV2::clone() const
00567 {
00568   QgsMarkerLineSymbolLayerV2* x = new QgsMarkerLineSymbolLayerV2( mRotateMarker, mInterval );
00569   x->setSubSymbol( mMarker->clone() );
00570   x->setOffset( mOffset );
00571   x->setPlacement( mPlacement );
00572   return x;
00573 }
00574 
00575 void QgsMarkerLineSymbolLayerV2::setWidth( double width )
00576 {
00577   mMarker->setSize( width );
00578 }
00579 
00580 double QgsMarkerLineSymbolLayerV2::width() const
00581 {
00582   return mMarker->size();
00583 }
00584 
00586 
00587 QgsLineDecorationSymbolLayerV2::QgsLineDecorationSymbolLayerV2( QColor color, double width )
00588 {
00589   mColor = color;
00590   mWidth = width;
00591 }
00592 
00593 QgsLineDecorationSymbolLayerV2::~QgsLineDecorationSymbolLayerV2()
00594 {
00595 }
00596 
00597 QgsSymbolLayerV2* QgsLineDecorationSymbolLayerV2::create( const QgsStringMap& props )
00598 {
00599   QColor color = DEFAULT_LINEDECORATION_COLOR;
00600   double width = DEFAULT_LINEDECORATION_WIDTH;
00601 
00602   if ( props.contains( "color" ) )
00603     color = QgsSymbolLayerV2Utils::decodeColor( props["color"] );
00604   if ( props.contains( "width" ) )
00605     width = props["width"].toDouble();
00606 
00607   return new QgsLineDecorationSymbolLayerV2( color, width );
00608 }
00609 
00610 QString QgsLineDecorationSymbolLayerV2::layerType() const
00611 {
00612   return "LineDecoration";
00613 }
00614 
00615 void QgsLineDecorationSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
00616 {
00617   QColor penColor = mColor;
00618   penColor.setAlphaF( context.alpha() );
00619   mPen.setWidth( context.outputLineWidth( mWidth ) );
00620   mPen.setColor( penColor );
00621   QColor selColor = context.selectionColor();
00622   if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() );
00623   mSelPen.setWidth( context.outputLineWidth( mWidth ) );
00624   mSelPen.setColor( selColor );
00625 }
00626 
00627 void QgsLineDecorationSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
00628 {
00629 }
00630 
00631 void QgsLineDecorationSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSymbolV2RenderContext& context )
00632 {
00633   // draw arrow at the end of line
00634 
00635   QPainter* p = context.renderContext().painter();
00636   if ( !p )
00637   {
00638     return;
00639   }
00640 
00641   int cnt = points.count();
00642   if ( cnt < 2 )
00643   {
00644     return;
00645   }
00646   QPointF p2 = points.at( --cnt );
00647   QPointF p1 = points.at( --cnt );
00648   while ( p2 == p1 && cnt )
00649     p1 = points.at( --cnt );
00650   if ( p1 == p2 ) {
00651     // this is a collapsed line... don't bother drawing an arrow
00652     // with arbitrary orientation
00653     return;
00654   }
00655 
00656   double angle = atan2( p2.y() - p1.y(), p2.x() - p1.x() );
00657   double size = context.outputLineWidth( mWidth * 8 );
00658   double angle1 = angle + M_PI / 6;
00659   double angle2 = angle - M_PI / 6;
00660 
00661   QPointF p2_1 = p2 - QPointF( size * cos( angle1 ), size * sin( angle1 ) );
00662   QPointF p2_2 = p2 - QPointF( size * cos( angle2 ), size * sin( angle2 ) );
00663 
00664   p->setPen( context.selected() ? mSelPen : mPen );
00665   p->drawLine( p2, p2_1 );
00666   p->drawLine( p2, p2_2 );
00667 }
00668 
00669 QgsStringMap QgsLineDecorationSymbolLayerV2::properties() const
00670 {
00671   QgsStringMap map;
00672   map["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
00673   map["width"] = QString::number( mWidth );
00674   return map;
00675 }
00676 
00677 QgsSymbolLayerV2* QgsLineDecorationSymbolLayerV2::clone() const
00678 {
00679   return new QgsLineDecorationSymbolLayerV2( mColor, mWidth );
00680 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines