[Qgis-developer] arrows on line strings?

Stefanie Tellex stefie10 at media.mit.edu
Fri Feb 1 23:37:48 EST 2008


Hi Tim,

Not sure what went wrong.  Here's another one against -R8098.

I generated it by running  svn diff > patch  from a checkout of 
https://svn.qgis.org/repos/qgis/trunk/qgis .  Did I generate it wrong?

This version adds an argument to drawLineString called drawArrows that 
defaults to false.  I called it with that argument only when the 
geometry is a linestring.  So arrows no longer appear on polygons or 
multi line strings, but appear on all line strings.

Stefanie

Tim Sutton wrote:
> Hi Stefanie
> 
> I tried to apply your patch:
> 
> [qgis] svn update -r 8092
> Na revisão 8092.
> [qgis] patch -p0 < ~/tmp/line_arrows.diff
> patching file src/core/qgsvectorlayer.cpp
> Hunk #1 FAILED at 425.
> Hunk #2 FAILED at 434.
> Hunk #3 FAILED at 452.
> 3 out of 3 hunks FAILED -- saving rejects to file
> src/core/qgsvectorlayer.cpp.rej
> 
> 
> I didnt have time to manually resolve the rejected but perhaps
> regenerating it off trunk might help. I can add a simple checkbox
> option to the vector props dialog and do the associated xml
> (de)serialisation. This would probably only happen in a month or so
> since we are in feature freeze for getting 0.9.2 final out (so I would
> target it for 0.9.3). I would suggest to go with your approach for now
> since we are trying to get 1.0 out and implementing the renderers
> approach described by Magnus will only happen post 1.0. On the other
> hand I have often been asked about the ability to show direction on
> lines so adding your basic implementation for now seems like a good
> way to go for 1.0 relase. If anyone vigorously disagrees let me know,
> otherwise I'll incorporate your patch in 0.9.3 with some additions
> from myself to enabled or disable line arrows via the layer props
> dialog, the vector api and the layer properties serialisation
> mechanism.
> 
> Best regards
> 
> Tim
> 
> 2008/2/1, Stefanie Tellex <stefie10 at media.mit.edu>:
>> Hi,
>>
>> The attached patch against R8092 draws arrows on all linestrings
>> everywhere, no matter what, using code swiped from this GPL v2.0
>> licensed file:
>> http://doc.trolltech.com/4.3/graphicsview-diagramscene-arrow-cpp.html
>>
>> What's the best way to control arrow drawing so it only shows up on
>> particular layers? Seems like it should be written to the xml file also,
>> in which case it might be better to just wait until better rendering
>> happens, and live with patching QGIS myself until then...?
>>
>> There's also a bug on multi-line-strings where an arrow line gets drawn
>> to some random coordinate in the upper left hand corner which I'm not
>> motivated to fix since I only need arrows on line-strings...
>>
>> Stefanie
>>
>> Martin Dobias wrote:
>>> On Jan 31, 2008 5:49 PM, Stefanie Tellex <stefie10 at media.mit.edu> wrote:
>>>> Hi,
>>>>
>>>> I would like to draw arrows on line strings, since they represent
>>>> movement vectors and I want to show the direction of movement.  I
>>>> couldn't find any way to do that in the gui or any obvious way in the
>>>> programmatic API.  What's the best way to add this feature or is it
>>>> there already somewhere?
>>> Currently QGIS renderers work in a way that they just set some
>>> properties for painting and let the vector layer to draw the polyline,
>>> so it's not possible to create a renderer which would e.g. render
>>> arrows in the direction of the flow. We should allow renderers to do
>>> arbitrary drawing in future.
>>>
>>> Now it will be more complicated to acquire this effect: you can
>>> generate some points (e.g. in the middle of every line segment) and
>>> determine the angle of direction. Such generated vector layer with
>>> points you can load to map canvas and for rendering set a SVG symbol
>>> with an arrow and set rotation field appropriately to the field you've
>>> generated.
>>>
>>> Martin
>>
>> Index: src/core/qgsvectorlayer.cpp
>> ===================================================================
>> --- src/core/qgsvectorlayer.cpp (revision 8092)
>> +++ src/core/qgsvectorlayer.cpp (working copy)
>> @@ -425,6 +425,7 @@
>>    // 255 = opaque
>>    //
>>    QPen myTransparentPen = p->pen(); // store current pen
>> +  QBrush brush = p->brush(); //to be kept as original
>>    QColor myColor = myTransparentPen.color();
>>    //only set transparency from layer level if renderer does not provide
>>    //transparency on class level
>> @@ -433,7 +434,9 @@
>>        myColor.setAlpha(mTransparencyLevel);
>>      }
>>    myTransparentPen.setColor(myColor);
>> +
>>    p->setPen(myTransparentPen);
>> +
>>    p->drawPolyline(pa);
>>
>>    // draw vertex markers if in editing mode, but only to the main canvas
>> @@ -449,9 +452,43 @@
>>           drawVertexMarker((int)(*xIt), (int)(*yIt), *p);
>>         }
>>      }
>> +  // draw arrows
>> +#define PI 3.14159
>> +  p->setBrush(QBrush(myColor, Qt::SolidPattern));
>> +
>> +  for (int i = 0; i < pa.size(); ++i)
>> +    {
>> +      if (i > 0)
>> +       {
>> +         QPointF p1 = pa[i];
>> +         QPointF p2 = pa[i-1];
>>
>> +         QLineF line = QLineF(p1, p2);
>> +         double angle = ::acos(line.dx() / line.length());
>> +         if (line.dy() >= 0)
>> +           {
>> +           angle = (PI * 2) - angle;
>> +           }
>> +
>> +         float arrowSize = 10;
>> +         QPointF arrowP1 =
>> +           line.p1() + QPointF(sin(angle + PI / 3) * arrowSize,
>> +                               cos(angle + PI / 3) * arrowSize);
>> +         QPointF arrowP2 =
>> +           line.p1() + QPointF(sin(angle + PI - PI / 3) * arrowSize,
>> +                               cos(angle + PI - PI / 3) * arrowSize);
>> +         QPolygonF arrowHead;
>> +         arrowHead << line.p1() << arrowP1 << arrowP2;
>> +         p->drawPolygon(arrowHead);
>> +
>> +
>> +       }
>> +      QgsDebugMsgLevel("pa" + QString::number(pa.point(i).x()), 2);
>> +      QgsDebugMsgLevel("pa" + QString::number(pa.point(i).y()), 2);
>> +    }
>>    //restore the pen
>>    p->setPen(pen);
>> +  p->setBrush(brush);
>>
>>    return ptr;
>>  }
>>
>> _______________________________________________
>> Qgis-developer mailing list
>> Qgis-developer at lists.qgis.org
>> http://lists.qgis.org/cgi-bin/mailman/listinfo/qgis-developer
>>
>>
> 
> 

-------------- next part --------------
Index: src/core/qgsvectorlayer.cpp
===================================================================
--- src/core/qgsvectorlayer.cpp	(revision 8098)
+++ src/core/qgsvectorlayer.cpp	(working copy)
@@ -353,7 +353,8 @@
     QPainter* p,
     QgsMapToPixel* mtp,
     QgsCoordinateTransform* ct,
-    bool drawingToEditingCanvas)
+    bool drawingToEditingCanvas,
+    bool drawArrows)
 {
   unsigned char *ptr = feature + 5;
   unsigned int wkbType = *((int*)(feature+1));
@@ -425,6 +426,7 @@
   // 255 = opaque
   //
   QPen myTransparentPen = p->pen(); // store current pen
+  QBrush brush = p->brush(); //to be kept as original
   QColor myColor = myTransparentPen.color();
   //only set transparency from layer level if renderer does not provide
   //transparency on class level
@@ -433,7 +435,9 @@
       myColor.setAlpha(mTransparencyLevel);
     }
   myTransparentPen.setColor(myColor);
+
   p->setPen(myTransparentPen);
+  
   p->drawPolyline(pa);
 
   // draw vertex markers if in editing mode, but only to the main canvas
@@ -449,9 +453,45 @@
 	  drawVertexMarker((int)(*xIt), (int)(*yIt), *p);
 	}
     }
-
+  // draw arrows
+  if (drawArrows) {
+#define PI 3.14159
+    p->setBrush(QBrush(myColor, Qt::SolidPattern));
+    
+    for (int i = 0; i < pa.size(); ++i)
+      {
+	if (i > 0) 
+	  {
+	    QPointF p1 = pa[i];
+	    QPointF p2 = pa[i-1];
+	    
+	    QLineF line = QLineF(p1, p2);
+	    double angle = ::acos(line.dx() / line.length());
+	    if (line.dy() >= 0)
+	      {
+		angle = (PI * 2) - angle;
+	      }
+	    
+	    float arrowSize = 10;
+	    QPointF arrowP1 = 
+	      line.p1() + QPointF(sin(angle + PI / 3) * arrowSize,
+				  cos(angle + PI / 3) * arrowSize);
+	    QPointF arrowP2 = 
+	      line.p1() + QPointF(sin(angle + PI - PI / 3) * arrowSize,
+				  cos(angle + PI - PI / 3) * arrowSize);
+	    QPolygonF arrowHead;
+	    arrowHead << line.p1() << arrowP1 << arrowP2;
+	    p->drawPolygon(arrowHead);
+	    
+	    
+	  }
+	QgsDebugMsgLevel("pa" + QString::number(pa.point(i).x()), 2);
+	QgsDebugMsgLevel("pa" + QString::number(pa.point(i).y()), 2);
+      }
+  }
   //restore the pen
   p->setPen(pen);
+  p->setBrush(brush);
   
   return ptr;
 }
@@ -3035,7 +3075,7 @@
                        p,
                        theMapToPixelTransform,
                        ct,
-                       drawingToEditingCanvas);
+                       drawingToEditingCanvas, TRUE);
         break;
       }
     case QGis::WKBMultiLineString:
Index: src/core/qgsvectorlayer.h
===================================================================
--- src/core/qgsvectorlayer.h	(revision 8098)
+++ src/core/qgsvectorlayer.h	(working copy)
@@ -459,7 +459,8 @@
                                 QPainter* p,
                                 QgsMapToPixel* mtp,
                                 QgsCoordinateTransform* ct,
-                                bool drawingToEditingCanvas);
+                                bool drawingToEditingCanvas,
+				bool drawArrows=FALSE);
 
   /** Draw the polygon as given in the WKB format. Returns a pointer to
    *  the byte after the end of the polygon binary data stream (WKB).


More information about the Qgis-developer mailing list