Page 1 of 1

Fixed Height Bars with Alternating Marks Position

Posted: Sun Mar 15, 2009 7:09 am
by 9092401
Hey,
I'm trying to create a graph with a fixed height, where the bars value will determine the relative width.
Also I need the marks position and length alternating in position, having odd marks above the graph and even ones below the graph.

In order to make the width relative I tried using Steema.TeeChart.Styles.HorizBar but I got the marks horizontal as well.

see attached image of the intended graph look
Image
The red braces & blue arrows are only for illustration purposes.

Cheers,
Elad

Posted: Mon Mar 16, 2009 12:44 pm
by 10050769
Hi qcrnd,


You coud use a similar code as next, for fix your issue:

InitializeChart

Code: Select all

        private void InitializeChart()
        {
            Steema.TeeChart.Styles.HorizBar hbar = new Steema.TeeChart.Styles.HorizBar(tChart1.Chart);
            hbar.FillSampleValues(4);
            hbar.ColorEach = true;
            hbar.MultiBar = Steema.TeeChart.Styles.MultiBars.SelfStack;
            tChart1.AfterDraw += new Steema.TeeChart.PaintChartEventHandler(tChart1_AfterDraw);
            tChart1.MouseUp += new MouseEventHandler(tChart1_MouseUp);
            tChart1.Draw();
        
        }
AfterDraw Event

Code: Select all

        void tChart1_AfterDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
        {
            RepositionMarks(tChart1[0]);
        }

Method RepositionMarks

Code: Select all

        private void RepositionMarks(Steema.TeeChart.Styles.Series series)
        {
            Steema.TeeChart.Styles.SeriesMarks.Position pos;
            series.Chart.AutoRepaint = false;
            for (int i = 0; i < series.Count; i++)
            {
                pos = series.Marks.Positions[i];
                pos.Custom = true;
                series.Marks.Arrow.Width = 2;
                series.Marks.Arrow.Color = Color.Black;

                int tmpX = tChart1.Axes.Bottom.CalcXPosValue(series.XValues[i]);
                int tmpHalfWidth = Convert.ToInt32(pos.Width/2);

                if (i == 0)
                {
                    pos.LeftTop.X = tmpX - Convert.ToInt32((tmpX - tChart1.Axes.Bottom.IStartPos)/2) - tmpHalfWidth;
                }
                else
                {
                    pos.LeftTop.X = series.Marks.Positions[i - 1].LeftTop.X + tmpX - tChart1.Axes.Bottom.IStartPos;
                }                

                pos.ArrowTo.X = pos.LeftTop.X + pos.Width / 2;
                pos.ArrowFrom.X = pos.ArrowTo.X;

                int tmp = ((Steema.TeeChart.Styles.HorizBar)series).BarBounds.Height;

                if (i % 2 == 0)
                {
                    pos.LeftTop.Y += tmp;
                    pos.ArrowFrom.Y = ((Steema.TeeChart.Styles.HorizBar)series).BarBounds.Bottom;
                }
                else
                {
                    pos.LeftTop.Y -= tmp;                    
                    pos.ArrowFrom.Y = ((Steema.TeeChart.Styles.HorizBar)series).BarBounds.Top;
                }

                pos.ArrowTo.Y = pos.LeftTop.Y;
            }
            series.Chart.AutoRepaint = true;
            series.Chart.Invalidate();

        }

I hope that you have been served my help

Thanks

Posted: Tue Mar 17, 2009 9:33 am
by 9092401
I'm still having some issues.
We build out chart differently, I'll try changing the adjustments to your code.

Thanks
Elad

-

Posted: Tue Mar 17, 2009 1:13 pm
by 9092401
I still encounter several problems:

1) I've tried correcting the positions and there are many offsets.

This is the chart is built:

Code: Select all

      foreach (KeyValuePair<string, int> val in Values)
      {
          HorizBar bar = new HorizBar(tChart1.Chart);
          bar.MultiBar = MultiBars.Stacked;
          bar.Cursor = Cursors.Hand;
          bar.BarHeightPercent = 100;

          bar.DepthPercent = 50;
          bar.Marks.Visible = true;
          bar.Color = GetColor(val.Key);
          bar.Add(val.Value, val.Key);

          bar.Title = string.Format("{0} {1}", val.Value, val.Key);
        }
      }

      tChart1.AfterDraw += new Steema.TeeChart.PaintChartEventHandler(RepositionChartMarks);
2) Since the marks are visible on creation, causing the chart doesn't occupy all the area, having the right area empty.

3) tChart1.Draw() method should gets System.Drawing.Graphics as a parameter, so I cannot invoke it after creating the chart.

Can you assist?

Thanks
Elad

Posted: Wed Mar 18, 2009 12:53 pm
by 10050769
Hi Edal,

Please, could you send us a simple example project we can run "as-is" to reproduce the problem here?
You can either post your files at news://www.steema.net/steema.public.attachments newsgroup or at ourupload page

Thanks,

File uploaded

Posted: Thu Mar 19, 2009 8:44 am
by 9092401
Hey Sandra,
I've uploaded the file, it is named "TChartSample.zip"
I added info in 1.txt file

Thanks
Elad

Posted: Fri Mar 20, 2009 3:38 pm
by narcis
Hi Elad,

Thanks for the example project. Compiling it with latest TeeChart for .NET v3 release available at the client area we could use tChart1.Draw() method. Could you please check if this solves the problem at your end? If it doesn't which is the exact problem you are having with marks positioning?

Thanks in advance.

Posted: Sun Mar 22, 2009 6:09 am
by 9092401
Thanks Narcis,
I will check the .Net V3.
Can you please also check regarding my two other questions, especially the reason the chart doesn't fill the entire tChart area becuase of the original marks position?

Thanks again
Elad

Posted: Mon Mar 23, 2009 2:47 pm
by narcis
Hi Elad,

Sure! Find below the answers to your questions:

2. Below you'll find modified code which works fine with your example:

Code: Select all

    public ChartForm()
    {
      InitializeComponent();
      CreateChart();
			this.Resize += new EventHandler(ChartForm_Resize);
    }

		void ChartForm_Resize(object sender, EventArgs e)
		{
			tChart1.Draw();
		}



    private bool CreateChart()
    {
      IDictionary<string, int> valuesDict = new Dictionary<string, int>();

      valuesDict.Add("opt A", 5);
      valuesDict.Add("option B", 2);
      valuesDict.Add("option CCC", 4);
      valuesDict.Add("D", 8);

      IDictionary<string, Color> colorsDict = new Dictionary<string, Color>();

      colorsDict.Add("opt A", Color.AliceBlue);
      colorsDict.Add("option B", Color.Chocolate);
      colorsDict.Add("option CCC", Color.Gold);
      colorsDict.Add("D", Color.SpringGreen);

			tChart1.Dock = DockStyle.Fill;
      tChart1.Series.Clear();
      tChart1.Legend.Visible = false;

      foreach (KeyValuePair<string, int> status in valuesDict)
      {
        // if there are no requirement with this status, don't add a series
        // (if its in the end of the bar, its color is shown)
        if (status.Value > 0)
        {
          HorizBar bar = new HorizBar(tChart1.Chart);
          bar.MultiBar = MultiBars.Stacked;
          bar.Cursor = Cursors.Hand;
          bar.BarHeightPercent = 100;

          bar.DepthPercent = 50;
          bar.Marks.Visible = true; // 12345 false;
          bar.Color = colorsDict[status.Key];
          bar.Add(status.Value, status.Key);

          bar.Title = string.Format("{0} {1}", status.Value, status.Key);
        }
      }

      tChart1.AfterDraw += new Steema.TeeChart.PaintChartEventHandler(RepositionChartMarks);

			tChart1.Draw();

      return true;
    }

    private void RepositionChartMarks(object sender, Steema.TeeChart.Drawing.Graphics3D g)
    {
      HorizBar series = null;
			Steema.TeeChart.Styles.SeriesMarks.Position pos = new SeriesMarks.Position();
			Steema.TeeChart.Styles.SeriesMarks.Position oldPos;

      for (int i = 0; i < tChart1.Series.Count; i++)
      {        
        series = (HorizBar)tChart1[i];
				series.Chart.AutoRepaint = false;
        series.Marks.Arrow.Width = 1;
        series.Marks.Arrow.Color = System.Drawing.Color.Black;

				oldPos = pos;
				pos = series.Marks.Positions[0];
				pos.Custom = true;
				pos.LeftTop.X = series.BarBounds.Left + series.BarBounds.Width / 2 - pos.Width / 2;
        pos.ArrowTo.X = pos.LeftTop.X + pos.Width / 2;
        pos.ArrowFrom.X = pos.ArrowTo.X;

        int tmp = Convert.ToInt32(series.BarBounds.Height / 3);

        if (i % 2 == 1)
        {          
          pos.ArrowFrom.Y = series.BarBounds.Bottom;
					pos.LeftTop.Y = pos.ArrowFrom.Y + tmp; 
        }
        else
        {
					pos.ArrowFrom.Y = series.BarBounds.Top;
					pos.LeftTop.Y = pos.ArrowFrom.Y - tmp;
        }

        pos.ArrowTo.Y = pos.LeftTop.Y;
      }
			series.Chart.AutoRepaint = true;
			series.Chart.Invalidate();
    }
3. In v3 you can use it as can be seen in the code above. In v2 you can do this:

Code: Select all

				Bitmap bmp = tChart1.Bitmap

Posted: Tue Mar 24, 2009 2:47 pm
by 9092401
Thanks, it works great.
only problem I have is a empty space in the right of the chart, see attached image:
Image

Instead of the chart taking the entire chart area width, it is behaving as if the default marks were in their default places thus reducing the actual bars width.

I tried changing the custom width but had no luck.

Any advice?
Thanks in advance
Elad

Posted: Tue Mar 24, 2009 4:17 pm
by narcis
Hi Elad,

In that case I'd use Annotation tools instead of series marks:

Code: Select all

    public ChartForm()
    {
      InitializeComponent();
      CreateChart();
			this.Resize += new EventHandler(ChartForm_Resize);
    }

		void ChartForm_Resize(object sender, EventArgs e)
		{
			tChart1.Draw();
		}

		private Steema.TeeChart.Tools.Annotation[] annotations;

    private bool CreateChart()
    {
      IDictionary<string, int> valuesDict = new Dictionary<string, int>();

      valuesDict.Add("opt A", 5);
      valuesDict.Add("option B", 2);
      valuesDict.Add("option CCC", 4);
      valuesDict.Add("D", 8);

      IDictionary<string, Color> colorsDict = new Dictionary<string, Color>();

      colorsDict.Add("opt A", Color.AliceBlue);
      colorsDict.Add("option B", Color.Chocolate);
      colorsDict.Add("option CCC", Color.Gold);
      colorsDict.Add("D", Color.SpringGreen);

			tChart1.Dock = DockStyle.Fill;
      tChart1.Series.Clear();
      tChart1.Legend.Visible = false;

      foreach (KeyValuePair<string, int> status in valuesDict)
      {
        // if there are no requirement with this status, don't add a series
        // (if its in the end of the bar, its color is shown)
        if (status.Value > 0)
        {
          HorizBar bar = new HorizBar(tChart1.Chart);
          bar.MultiBar = MultiBars.Stacked;
          bar.Cursor = Cursors.Hand;
          bar.BarHeightPercent = 100;

          bar.DepthPercent = 50;
          bar.Marks.Visible = false; // 12345 false;
          bar.Color = colorsDict[status.Key];
          bar.Add(status.Value, status.Key);

          bar.Title = string.Format("{0} {1}", status.Value, status.Key);
        }
      }
      
			annotations = new Steema.TeeChart.Tools.Annotation[tChart1.Series.Count];
			for (int i = 0; i < tChart1.Series.Count; i++)
			{
				annotations[i] = new Steema.TeeChart.Tools.Annotation(tChart1.Chart);
				annotations[i].Text = tChart1[i].Labels[0];
				annotations[i].Callout.Arrow.Visible = true;
				annotations[i].Callout.Arrow.Color = Color.Black;
				annotations[i].Callout.Arrow.Width = 1;
			}

			tChart1.AfterDraw += new Steema.TeeChart.PaintChartEventHandler(RepositionChartMarks);
			tChart1.Draw();

      return true;
    }

    private void RepositionChartMarks(object sender, Steema.TeeChart.Drawing.Graphics3D g)
    {
      HorizBar series = null;
			Steema.TeeChart.Tools.Annotation a;
			
      for (int i = 0; i < tChart1.Series.Count; i++)
      {        
        series = (HorizBar)tChart1[i];
				a = annotations[i];
				
				a.Shape.CustomPosition = true;
				a.Shape.Left = series.BarBounds.Left + series.BarBounds.Width / 2 - a.Width / 2;
				a.Callout.XPosition = a.Shape.Left + a.Width / 2;

				int tmp = Convert.ToInt32(series.BarBounds.Height / 3);

				if (i % 2 == 1)
				{
					a.Callout.YPosition = series.BarBounds.Bottom;
					a.Shape.Top = a.Callout.YPosition + tmp;
				}
				else
				{
					a.Callout.YPosition = series.BarBounds.Top;
					a.Shape.Top = a.Callout.YPosition - tmp;
				}
      }
    }

Posted: Wed Mar 25, 2009 11:32 am
by 9092401
Thanks a lot for all your help