We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Custom points on box and whisker at multiple Y positions

Right now I have a box and whisker chart (image: original.png) and I need to plot custom points on each of the individual boxes at different Y values (image: required.png). I am finding it difficult to do because all the boxes (of one item) have the same X coordinate. How can I determine the actual X coordinates of the individual boxes?

Attachment: Pictures_9bd306ed.zip

10 Replies

SK Saravana Kumar Kanagavel Syncfusion Team August 25, 2016 10:51 AM UTC

Hi Swetaketu, 
 
Thanks for contacting Syncfusion Support. 
We have analyzed your query and created a sample based on your requirement . In the sample, we have drawn custom points into the box and whisker chart. 
Please refer the code example below 
 
[C#] 
         ChartCustomPoint ccp = new ChartCustomPoint(); 
            ccp.XValue = this.chartControl1.Series[0].Points[0].X - 0.23; 
            ccp.YValue = this.chartControl1.Series[0].Points[0].YValues[3]; 
            ccp.CustomType = ChartCustomPointType.ChartCoordinates; 
            ccp.SeriesIndex = 0; 
            ccp.PointIndex = 0; 
            ccp.Border.Color = Color.Black; 
            ccp.Symbol.Color = Color.Yellow; 
            ccp.Symbol.Size = new System.Drawing.Size(15, 15); 
            ccp.Symbol.Shape = ChartSymbolShape.Circle; 
            this.chartControl1.CustomPoints.Add(ccp); 
 
        ChartCustomPoint ccp1 = new ChartCustomPoint(); 
            ccp1.XValue = this.chartControl1.Series[1].Points[0].X; 
            ccp1.YValue = this.chartControl1.Series[1].Points[0].YValues[6]; 
            ccp1.CustomType = ChartCustomPointType.ChartCoordinates; 
            ccp1.SeriesIndex = 1; 
            ccp1.PointIndex = 0; 
            ccp1.Border.Color = Color.Black; 
            ccp1.Symbol.Color = Color.Yellow; 
            ccp1.Symbol.Size = new System.Drawing.Size(15, 15); 
            ccp1.Symbol.Shape = ChartSymbolShape.Circle; 
 
            this.chartControl1.CustomPoints.Add(ccp1); 
 
        ChartCustomPoint ccp2 = new ChartCustomPoint(); 
            ccp2.XValue = this.chartControl1.Series[2].Points[0].X + 0.23; 
            ccp2.YValue = this.chartControl1.Series[2].Points[0].YValues[3]; 
            ccp2.CustomType = ChartCustomPointType.ChartCoordinates; 
            ccp2.SeriesIndex = 2; 
            ccp2.PointIndex = 0; 
            ccp2.Border.Color = Color.Black; 
            ccp2.Symbol.Color = Color.Yellow; 
            ccp2.Symbol.Size = new System.Drawing.Size(15, 15); 
            ccp2.Symbol.Shape = ChartSymbolShape.Circle; 
 
            this.chartControl1.CustomPoints.Add(ccp2); 
  
In the above code, we have drawn the custom point symbol by using “ChartCustomPoint” class and also have set the fill and border color for point symbol. We are fetching the x and y value of the particular point and placing custom point at that value. 
And you can find the sample from the below location 
 
  
Please find the output of the sample below 
 
 
Please let us know if you have any concern. 
 
Regards, 
Saravana Kumar K 



SM Swetaketu Majumder August 25, 2016 12:27 PM UTC

Hi Saravana,

Thank you for the response. How did you determine 0.23? What would be the value if there were 5 series in place of three? or may be two series?

Thanks and regards,
Swetaketu


SK Saravana Kumar Kanagavel Syncfusion Team August 26, 2016 12:16 PM UTC

Hi Swetaketu, 
 
Thanks for your update. 
We have analyzed your query. In previous updated , we have adjust the x value to draw the custom point at the center of the box and wisher chart manually. And if you wish to draw the custom point generically, then you can use the “ColumnDrawMode” as ClusteredMode. By using this property, you can draw the custom point at exact positioning into the column. This property is used to place the column without consider the other series and place the columns as like cluster. And we would like to inform that if you want to customize the column width, then you can set the “ColumnWidthMode” as FixedWidthMode and also you can set the any int value specify to the “ColumnFixedWidth” property. 
 
And Please refer the code example below 
 
[C#] 
this.chartControl1.ColumnWidthMode = ChartColumnWidthMode.FixedWidthMode; 
this.chartControl1.ColumnFixedWidth = 50; 
this.chartControl1.ColumnDrawMode = ChartColumnDrawMode.ClusteredMode; 
         ChartCustomPoint ccp = new ChartCustomPoint(); 
            ccp.XValue = this.chartControl1.Series[0].Points[0].X; 
            ccp.YValue = this.chartControl1.Series[0].Points[0].YValues[3]; 
            ccp.CustomType = ChartCustomPointType.ChartCoordinates; 
 
            ccp.SeriesIndex = 0; 
            ccp.PointIndex = 0; 
            ccp.Border.Color = Color.Black; 
            ccp.Symbol.Color = Color.Yellow; 
            ccp.Symbol.Size = new System.Drawing.Size(15, 15); 
            ccp.Symbol.Shape = ChartSymbolShape.Circle; 
            this.chartControl1.CustomPoints.Add(ccp); 
 
         ChartCustomPoint ccp1 = new ChartCustomPoint(); 
            ccp1.XValue = this.chartControl1.Series[1].Points[0].X; 
            ccp1.YValue = this.chartControl1.Series[1].Points[0].YValues[6]; 
            ccp1.CustomType = ChartCustomPointType.ChartCoordinates; 
            ccp1.SeriesIndex = 1; 
            ccp1.PointIndex = 0; 
            ccp1.Border.Color = Color.Black; 
            ccp1.Symbol.Color = Color.Yellow; 
            ccp1.Symbol.Size = new System.Drawing.Size(15, 15); 
            ccp1.Symbol.Shape = ChartSymbolShape.Circle; 
 
            this.chartControl1.CustomPoints.Add(ccp1); 
 
         ChartCustomPoint ccp2 = new ChartCustomPoint(); 
            ccp2.XValue = this.chartControl1.Series[2].Points[0].X; 
            ccp2.YValue = this.chartControl1.Series[2].Points[0].YValues[3]; 
            ccp2.CustomType = ChartCustomPointType.ChartCoordinates; 
            ccp2.SeriesIndex = 2; 
            ccp2.PointIndex = 0; 
            ccp2.Border.Color = Color.Black; 
            ccp2.Symbol.Color = Color.Yellow; 
            ccp2.Symbol.Size = new System.Drawing.Size(15, 15); 
            ccp2.Symbol.Shape = ChartSymbolShape.Circle; 
 
            this.chartControl1.CustomPoints.Add(ccp2); 
 
            ChartCustomPoint ccp3 = new ChartCustomPoint(); 
            ccp3.XValue = this.chartControl1.Series[3].Points[0].X; 
            ccp3.YValue = this.chartControl1.Series[3].Points[0].YValues[6]; 
            ccp3.CustomType = ChartCustomPointType.ChartCoordinates; 
            ccp3.SeriesIndex = 3; 
            ccp3.PointIndex = 0; 
            ccp3.Border.Color = Color.Black; 
            ccp3.Symbol.Color = Color.Yellow; 
            ccp3.Symbol.Size = new System.Drawing.Size(15, 15); 
            ccp3.Symbol.Shape = ChartSymbolShape.Circle; 
 
            this.chartControl1.CustomPoints.Add(ccp3); 
 
            ChartCustomPoint ccp4 = new ChartCustomPoint(); 
            ccp4.XValue = this.chartControl1.Series[4].Points[0].X; 
            ccp4.YValue = this.chartControl1.Series[4].Points[0].YValues[3]; 
            ccp4.CustomType = ChartCustomPointType.ChartCoordinates; 
            ccp4.SeriesIndex = 4; 
            ccp4.PointIndex = 0; 
            ccp4.Border.Color = Color.Black; 
            ccp4.Symbol.Color = Color.Yellow; 
            ccp4.Symbol.Size = new System.Drawing.Size(15, 15); 
            ccp4.Symbol.Shape = ChartSymbolShape.Circle; 
 
            this.chartControl1.CustomPoints.Add(ccp4); 
 
  
In the above code, we have setting the “ColumnDrawMode” as ClusteredMode to draw the custom point without any added value in x values.  
And we have also prepare a sample for your reference and attached in the below location 

  
Please find the output of the sample below 
 
 
 
Please let us know if you have any concern. 
 
Regards, 
Saravana Kumar K. 



SM Swetaketu Majumder August 26, 2016 03:39 PM UTC

But this defeats the whole purpose of my chart. Let me try to explain what I am trying to do here.

Imagine there are three employees Arun, Dinesh and Tania. I have their sales figures for every month of the last two years. I have plotted them on a chart (see image). 


Now, I want to plot the value of each month 

Attachment: example1_5fe020ae.zip


SM Swetaketu Majumder August 26, 2016 03:42 PM UTC

Sorry the last reply was not complete. 

Now I want to plot the value of each month as custom points on the individual bars. Please tell me how to do this without hard-coding anything.

You can replace the contents of the InitializeChartData() method in the sample you sent me with the following to get the chart that I have sent you:

            this.chartControl1.PrimaryXAxis.TickLabelsDrawingMode = ChartAxisTickLabelDrawingMode.UserMode;

            this.chartControl1.PrimaryXAxis.Labels.Clear();
            chartControl1.PrimaryXAxis.Labels.Add(new ChartAxisLabel("Arun", 1));
            chartControl1.PrimaryXAxis.Labels.Add(new ChartAxisLabel("Dinesh", 2));
            chartControl1.PrimaryXAxis.Labels.Add(new ChartAxisLabel("Tania", 3));

            ChartSeries BoxPlot = new ChartSeries("Year 1", ChartSeriesType.BoxAndWhisker);
            BoxPlot.ConfigItems.BoxAndWhiskerItem.PercentileMode = true;

            ChartSeries BoxPlot1 = new ChartSeries("Year 2", ChartSeriesType.BoxAndWhisker);
            BoxPlot1.ConfigItems.BoxAndWhiskerItem.PercentileMode = true;
       
            BoxPlot.Points.Add(1, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 10, 20);   // Year 1 data for Arun
            BoxPlot.Points.Add(2, 30, 40, 50, 60, 70, 80, 90, 100, 110, 100, 100, 10);   // Year 1 data for Dinesh
            BoxPlot.Points.Add(3, 35, 25, 22, 55, 68, 80, 95, 110, 110, 120, 100, 30);  // Year 1 data for Tania

            BoxPlot1.Points.Add(1, 10, 20, 30, 40, 50, 40, 30, 20, 10, 50, 20, 10); // Year 2 data for Arun
            BoxPlot1.Points.Add(2, 10, 20, 30, 60, 20, 100, 80, 60, 74, 45, 65, 100); // Year 2 data for Dinesh
            BoxPlot1.Points.Add(3, 2, 70, 130, 80, 20, 100, 80, 60, 174, 75, 65, 100); // Year 2 data for Tania

            this.chartControl1.Series.Add(BoxPlot);
            this.chartControl1.Series.Add(BoxPlot1);


SK Saravana Kumar Kanagavel Syncfusion Team August 29, 2016 12:49 PM UTC

Hi Swetaketu, 
 
Thanks for your update. 
We have analyzed your query. And we have replaced the your code and drawn the custom point generically as an work around. In the sample, we have find the box and whisker column bounds on “ChartImage” event. In the event, we have drawn the custom point with the box and whisker column bounds for each point in each series. 
 
And Please refer the code example below 
 
[C#] 
public partial class Form1 : MetroForm 
    { 
        private bool triggered = true; 
        private System.Drawing.RectangleF region1; 
    
   public Form1() 
      { 
         
       InitializeChartData(); 
        
      } 
         protected void InitializeChartData() 
        { 
            this.chartControl1.PrimaryXAxis.TickLabelsDrawingMode = ChartAxisTickLabelDrawingMode.UserMode; 
 
            this.chartControl1.PrimaryXAxis.Labels.Clear(); 
            chartControl1.PrimaryXAxis.Labels.Add(new ChartAxisLabel("Arun", 1)); 
            chartControl1.PrimaryXAxis.Labels.Add(new ChartAxisLabel("Dinesh", 2)); 
            chartControl1.PrimaryXAxis.Labels.Add(new ChartAxisLabel("Tania", 3)); 
 
            ChartSeries BoxPlot = new ChartSeries("Year 1", ChartSeriesType.BoxAndWhisker); 
            BoxPlot.ConfigItems.BoxAndWhiskerItem.PercentileMode = true; 
            this.chartControl1.CalcRegions = true; 
            ChartSeries BoxPlot1 = new ChartSeries("Year 2", ChartSeriesType.BoxAndWhisker); 
            BoxPlot1.ConfigItems.BoxAndWhiskerItem.PercentileMode = true; 
            BoxPlot.Points.Add(1, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 10, 20);   // Year 1 data for Arun 
            BoxPlot.Points.Add(2, 30, 40, 50, 60, 70, 80, 90, 100, 110, 100, 100, 10);   // Year 1 data for Dinesh 
            BoxPlot.Points.Add(3, 35, 25, 22, 55, 68, 80, 95, 110, 110, 120, 100, 30);  // Year 1 data for Tania 
 
            BoxPlot1.Points.Add(1, 10, 20, 30, 40, 50, 40, 30, 20, 10, 50, 20, 10); // Year 2 data for Arun 
            BoxPlot1.Points.Add(2, 10, 20, 30, 60, 20, 100, 80, 60, 74, 45, 65, 100); // Year 2 data for Dinesh 
            BoxPlot1.Points.Add(3, 2, 70, 130, 80, 20, 100, 80, 60, 174, 75, 65, 100); // Year 2 data for Tania 
 
            this.chartControl1.ChartImage += chartControl1_ChartImage; 
            this.chartControl1.Resize +=chartControl1_Resize; 
            this.chartControl1.Series.Add(BoxPlot); 
            this.chartControl1.Series.Add(BoxPlot1); 
 
        } 
 
     void chartControl1_ChartImage(object sender, ChartAreaImageEventArgs e) 
        { 
 
            if (triggered) 
            { 
                var count = 0; 
                for (var i = 0; i < this.chartControl1.ChartRegions.Count; i++) 
                { 
                    if (this.chartControl1.ChartRegions[i].IsChartPoint) 
                    { 
                        region1 = this.chartControl1.ChartRegions[i].Region.GetBounds(Graphics.FromImage(e.BufferImage)); 
                        if (count % this.chartControl1.Series.Count == 0) 
                        { 
                            ChartCustomPoint ccp = new ChartCustomPoint(); 
                            ccp.CustomType = ChartCustomPointType.Pixel; 
                            ccp.XValue = region1.X + region1.Width / 2; 
                            ccp.YValue = region1.Y + region1.Height / 2; 
                            ccp.Border.Color = Color.Black; 
                            ccp.Symbol.Color = Color.Yellow; 
                            ccp.Symbol.Size = new System.Drawing.Size(15, 15); 
                            ccp.Symbol.Shape = ChartSymbolShape.Circle; 
                            this.chartControl1.CustomPoints.Add(ccp); 
                        } 
                        count++; 
                    } 
                } 
 
            } 
            triggered = false; 
 
            this.chartControl1.Redraw(true); 
        } 
 
        void chartControl1_Resize(object sender, EventArgs e) 
        { 
            triggered = true; 
            this.chartControl1.CustomPoints.Clear(); 
            this.chartControl1.Redraw(true); 
             
        } 
 
  
In the above code, we have drawn the custom point using “ChartImage” event and also when resizing the form, the custom point drawn at exact positioning by using “Resize” event. In the event, we have clear the already drawn of custom points and redrawing the chart again. Now the custom points are rendered generically at the center of box and whisker chart. 
 
And we have also prepared a sample for your reference and attached in the below location 
 
  
Please find the output of the sample below 
 
 
 
 
Please let us know if you have any concern. 
 
Regards, 
Saravana Kumar K 



SM Swetaketu Majumder August 29, 2016 08:44 PM UTC

Hi Saravana,

Thank you for the sample. It solves part of the problem. You have plotted custom points at the center of the regions. That is not what I need. You have used pixels for Y coordinates but I have absolute values. So please tell me how can I convert those values to pixels for Y coordinates? And also, when the chart is zoomed, the region will change and so the points will need to be re-calculated correctly. Please investigate that as well.


JA Jayavigneshwaran Syncfusion Team August 30, 2016 10:55 AM UTC

Hi Swetaketu, 
Thanks for your update and we have analyzed your query. 

Query #1: how can I convert those values to pixels for Y coordinates? 
Response: You can obtain the coordinates of the chart point by using the GetPointByValue method in ChartArea. 

[C#] 
//... 
if (count % this.chartControl1.Series.Count == 0) 
    { 
      int YValue = 50; // you can modify this with your y value 
      ChartCustomPoint ccp = new ChartCustomPoint(); 
      ccp.CustomType = ChartCustomPointType.Pixel; 
      ccp.XValue = region1.X + region1.Width / 2;  // setting x value as pixel 
      ChartPoint point = new ChartPoint(0, YValue);        
      ccp.YValue = this.chartControl1.ChartArea.GetPointByValue(point).Y; // converting y value as pixel                                                               
      ccp.Border.Color = Color.Black; 
      ccp.Symbol.Color = Color.Yellow; 
      ccp.Symbol.Size = new System.Drawing.Size(15, 15); 
      ccp.Symbol.Shape = ChartSymbolShape.Circle; 
      this.chartControl1.CustomPoints.Add(ccp); 
    } 
//... 

In the above code we are creating custom points and adding those to chart. X value of the custom point is calculated based on region X and width values of box and whisker chart. And since Y value are being constant, we are converting the y values into coordinates and setting it to the custom points. 

In the below screen shot, all the custom points in chart are placed at the YValue 50. 
 

Query #2: when the chart is zoomed, the region will change and so the points will need to be re-calculated correctly 
Response: As like resize, also on zooming the chart visible range/ size of the chart gets changed. So we have to rearrange the custom points which got rendered based on the chart coordinates. So please follow the same steps as we did for chart resize. 

[C#] 
//... 
 
this.chartControl1.VisibleRangeChanging += chartControl1_VisibleRangeChanging; 
 
//... 
 
void chartControl1_VisibleRangeChanging(object sender, ChartAxisZoomingArgs args) 
        { 
            triggered = true; 
            this.chartControl1.CustomPoints.Clear(); 
            this.chartControl1.Redraw(true); 
        } 

In the above code we have specified the VisibleRangeChanging event which got triggered on zooming. And on that we are clearing the old custom points and redraw the chart with new custom points. 
So the point will be placed in exact position also on zooming. 
 

We have modified these changes in the previously provided sample and you can find it from the below location. 

Please let us know if you have any concern. 

Thanks, 
Jayavigneshwaran 



SM Swetaketu Majumder August 30, 2016 08:26 PM UTC

Thank you Jayavigneshwaran. That was precisely what I needed. Thank you so much!

Regards,
Swetaketu


SK Saravana Kumar Kanagavel Syncfusion Team August 31, 2016 09:29 AM UTC

Hi Swetaketu, 
 
Thanks for your update. 
 
Please let us know if you need any other assistance on this. 
 
Regards, 
Saravana Kumar K 


Loader.
Live Chat Icon For mobile
Up arrow icon