Page 1 of 1

Best Approach to Draw a Single Arrow Head on a Line Series

Posted: Thu Apr 13, 2017 10:46 pm
by 16080652
Hello All,

I have been searching the .NET forum and have a possible approach. Let me explain what is intended on the Chart user interface, and then list some code that could accomplish that. I am looking for assistance on determining if there is a better way (or best) that I am missing.

After (or while) creating new Series and then adding them to a single Chart component, all of them need an arrow head drawn at approximately 75 percent of the traversal along each series. The arrow head points in the direction of how real life things like steam move down a pipe. Only a single point is needed for the arrow head. I am aware of the TeeChart.Styles.Arrow series and its Add method to receive two sets of x, y coordinates to draw the arrow head. The example code I have created is based on this post: TeeChart.Styles.Arrow.LinePen Issues http://www.teechart.net/support/viewtop ... ilit=arrow

Code: Select all

   TeeChart.Styles.Arrow arrowStyle = new TeeChart.Styles.Arrow(tChart1.Chart);
   arrowStyle.ArrowHeight = 20;
   arrowStyle.ArrowWidth = 20;
   arrowStyle.Pointer.Pen.Width = 3;
   arrowStyle.Pointer.Pen.Style = System.Drawing.Drawing2D.DashStyle.Solid;
   arrowStyle.Add(13, 24, 13.8, 23, Color.LimeGreen);
   tChart1.Series.Add(arrowStyle);
To see the "one point" arrowStyle appear, the button click event has to fire twice. It does not matter if

Code: Select all

tChart1.Invalidate()
is called after the

Code: Select all

tChart1.Series.Add(arrowStyle)
line either. Two button click events will cause the one arrowStyle to appear. I am not sure if I am missing something in a property on the tChart1. It is possible.

Regardless, is there a better way to have a single arrow head appear on a line series, approximately 75 percent of the traversal along the series? For example, The above approach would mean that if there are 3000 independent line series, there would be 3000 independent single point "arrow head" TeeChart.Styles.Arrow series, for a grand total of 6000 series on a single chart.

If a single method exists within one of the series objects, it would be ideal if a single x, y coordinate can be given and the respective angle to match the line series directly beneath it. In other words, the arrow has to be pointing in the correct flow direction. The closest method I can find that is similar to the description is TeeChart.Drawing.TextShape.DrawRectRotated here: http://www.teechart.net/docs/teechart/n ... Method.htm. This special x, y coordinate and angle parameters method is definitely not a requirement. I would like to know if it exists to draw an arrow head as described above. Thank you all for your assistance.

Sincerely,

BR&E

Re: Best Approach to Draw a Single Arrow Head on a Line Series

Posted: Tue Apr 18, 2017 9:21 am
by Christopher
Hello,
br&e wrote:This special x, y coordinate and angle parameters method is definitely not a requirement. I would like to know if it exists to draw an arrow head as described above. Thank you all for your assistance.
possibly the easiest way to achieve this would be to custom draw an arrow onto the TeeChart canvas - this can be done using one of the TeeChart events and the canvas Arrow method, as in this example:

Code: Select all

    Line line;
    private void InitializeChart()
    {
      tChart1.Aspect.View3D = false;

      line = new Line(tChart1.Chart);
      line.FillSampleValues();

      tChart1.AfterDraw += TChart1_AfterDraw;
    }

    private void TChart1_AfterDraw(object sender, Graphics3D g)
    {
      int x = line.CalcXPos(5);
      int y = line.CalcYPos(5);

      Point from = new Point(x - 25, y);
      Point to = new Point(x + 25, y);

      g.Brush.Color = line.Color;
      g.Arrow(true, from, to, 25, 25, 0);
    }
is this a satisfactory solution for you?

Re: Best Approach to Draw a Single Arrow Head on a Line Series

Posted: Wed Apr 19, 2017 7:39 pm
by 16080652
Thank you Christopher. I have tested the implementation. The g.Arrow is much larger than what is needed.

I have attached a screen capture of the desired look. The added arrow head is inside the red circle. Generally, the arrow head looks like two lines at the correct orientation relative to the line segment slope. The line and arrow series' widths are the same.

Note that I have to force the TeeChart.Invalidate() method to be called twice to render the arrow series' single point. The two Invalidate() invocations occur regardless of using the Graphics3DDirect2D object. When the line series is added, a single Invalidate() call renders the new line. Nearly all TeeChart properties are the default values. Is there a property value I need to set differently in the Windows Form constructor, after the .Net InitializeComponent method returns?

Re: Best Approach to Draw a Single Arrow Head on a Line Series

Posted: Thu Apr 20, 2017 12:37 pm
by Christopher
You're welcome.

Well, another alternative is to draw your own arrows - this simple example draws an arrow orientated along the vector to the specified series point (AtPoint) from the previous series point (AtPoint - 1):

Code: Select all

    Line line;
    private void InitializeChart()
    {
      tChart1.Aspect.View3D = false;

      line = new Line(tChart1.Chart);
      line.LinePen.Width = 3;
      line.FillSampleValues();

      tChart1.AfterDraw += TChart1_AfterDraw;
    }

    private void TChart1_AfterDraw(object sender, Graphics3D g)
    {
      Action<int, int> Arrow = (AtPoint, Size) =>
      {
        Point to = new Point(line.CalcXPos(AtPoint), line.CalcYPos(AtPoint));
        Point from = new Point(line.CalcXPos(AtPoint - 1), line.CalcYPos(AtPoint - 1));

        Point difference = new Point(to.X - from.X, to.Y - from.Y);
        double tmp = Math.Sqrt(Math.Pow(difference.X, 2) + Math.Pow(difference.Y, 2));
        PointF vector = new PointF((difference.X / (float)tmp), ((difference.Y / (float)tmp)));
        PointF perpendicular = new PointF(vector.Y, -vector.X);

        Point online = new Point(Utils.Round(to.X - Utils.Round(vector.X * Size)), Utils.Round(to.Y - Utils.Round(vector.Y * Size)));
        Point topleft = new Point(Utils.Round(online.X - Utils.Round(perpendicular.X * Size)), Utils.Round(online.Y - Utils.Round(perpendicular.Y * Size)));
        Point bottomleft = new Point(Utils.Round(online.X + Utils.Round(perpendicular.X * Size)), Utils.Round(online.Y + Utils.Round(perpendicular.Y * Size)));

        g.Line(topleft, to);
        g.Line(bottomleft, to);
      };

      g.Pen.Color = line.Color;
      g.Pen.Width = line.LinePen.Width;
      Arrow(5, 10);
    }
TChart636282886363181283.png
TChart636282886363181283.png (21.94 KiB) Viewed 11268 times

Re: Best Approach to Draw a Single Arrow Head on a Line Series

Posted: Tue May 02, 2017 9:28 pm
by 16080652
Thank you again, Christopher.

Your first approach is what is in use now. The zooming in and out scaling works best with that. The initial rendering zoom setting is set such that the user will see the double line style in the first example. If the user zooms in for a close up view, the arrow expands to the larger style. It turns out that that automatic response helps our end users the most.

Sincerely,

BR&E