Quantum GIS API Documentation
1.7.4
|
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 }