Profile Picture

Tooltip Line Chart

Posted By Marc Welk 13 Years Ago
Author
Message
Nevron Support
Posted 13 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)

Group: Forum Members
Last Active: Last Week
Posts: 3,054, Visits: 4,009

Hi Marc,

The approach to sampling is very straight forward - the following code implements the algorithm proposed above:

   // init array with some random data
   double[] yValues = new double[100000];
   double[] xValues = new double[100000];

   for (int i = 0; i < 100000; i++)
   {
    yValues[i] = Math.Sin((double)i / 10000) * 100;
    xValues[i] = i;
   }

   //1. Calculate min max
   double minX = xValues[0];
   double maxX = xValues[0];

   double minY = xValues[0];
   double maxY = xValues[0];

   for (int i = 0; i < 100000; i++)
   {
    minX = Math.Min(minX, xValues[i]);
    maxX = Math.Max(maxX, xValues[i]);

    minY = Math.Min(minY, yValues[i]);
    maxY = Math.Max(maxY, yValues[i]);
   }

   //2. calculate box
   double boxSemiWidth = (maxX - minX) / 200;
   double boxSemiHeight = (maxY - minY) / 200;

   //3. sample data
   int boxCount = 0;
   double boxStartX = 0;
   double boxStartY = 0;
   double boxSumX = 0;
   double boxSumY = 0;

   NLineSeries line = new NLineSeries();
   line.UseXValues = true;
   line.DataLabelStyle.Visible = false;

   for (int i = 0; i < xValues.Length; i++)
   {
    if (boxCount != 0)
    {
     // check if we can add current to box
     if (Math.Abs(xValues[i] - boxStartX) < boxSemiWidth &&
      Math.Abs(yValues[i] - boxStartY) < boxSemiHeight)
     {
      boxSumX += xValues[i];
      boxSumY += yValues[i];
      boxCount++;

      continue;
     }

     // otherwise output current box
     line.Values.Add(boxSumY / boxCount);
     line.XValues.Add(boxSumX / boxCount);
    }

    // start new box
    boxSumX = xValues[i];
    boxSumY = yValues[i];

    boxStartX = xValues[i];
    boxStartY = yValues[i];

    boxCount = 1;
   }

   if (boxCount > 0)
   {
    // output trailing box
    line.Values.Add(boxSumY / boxCount);
    line.XValues.Add(boxSumX / boxCount);
   }

   // add line to chart
   NChart chart = nChartControl1.Charts[0];
   chart.Series.Add(line);

Regarding the HTML problem. When you have many data points with interactivity the control will generate an image map area for each one of them. This can lead to a huge HTML image map that will choke any browser. Therefore you need to resample in order to reduce the generated image map.

Hope this helps...



Best Regards,
Nevron Support Team



Marc Welk
Posted 13 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)

Group: Forum Members
Last Active: 13 Years Ago
Posts: 2, Visits: 1

Hi and thanks for your Post,

ok i understand or not .. is there no chance to create the complete Chart without building an average ? When i create the Line Chart without Tooltips everything is ok and it doesn´t matter if there 20000 or 500000 DataPoints.

You see maybe i don´t understand what you mean .. can you explain your Solution in a little Example ?

thanks Marc

PS : I think my confusion is complete



Nevron Support
Posted 13 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)Supreme Being (4,435 reputation)

Group: Forum Members
Last Active: Last Week
Posts: 3,054, Visits: 4,009

Hi Marc,
The problem in this case is that the generated HTML map will become too heavy as it will contain at least 20000 separate items. The solution is to resample the data prior to feeding it to the chart. A simple sampling will involve the following steps:

1. Determine the min/max values for the x and y values of all data points.

2. Calculate a xlength and ylength values such that - xlegnth = that (xmax - xmin) / 100, ylength = (ymax - ymin) / 100.

3. Start to iterate trough the data. For each set of points that are closer to each other than the calculated xlength and ylength - sum all points and output the average.

Hope this helps - let us know if you have any questions or meet any problems with the implementation.



Best Regards,
Nevron Support Team



Marc Welk
Posted 13 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)Forum Newbie (2 reputation)

Group: Forum Members
Last Active: 13 Years Ago
Posts: 2, Visits: 1
Hello,

i create a simple Line Chart in a Web-Application. Now i want to add Tooltips for each DataPoint. The Problem is when i want to create a Line Chart with over 20000 DataPoints, first the Browser
load the Application very slow, second the CPU Usage came from 5% to 30% and third when i move the Mouse over an DataPoint the CPU Usage become 50%.
Firefox works very slow but it works. The IE8 crashed with each Mouse over.

I sampled two Methods to add Tooltips, but both bring the same results :

first :

ncwc:NChartControl
ID="NChartControl1"
runat="server">
ncwc:NChartControl>

Dim CH As NCartesianChart = NChartControl1.Charts(0)

Dim line As NLineSeries = CType(CH.Series(b), NLineSeries)

line.Values.AddRange(CType(yValues(b), ArrayList))
line.XValues.AddRange(CType(xValues(b), ArrayList))

For i As Integer = 0 To line.Values.Count - 1
Dim DateVal As DateTime = Convert.ToDateTime(line.XValues(i))
Dim tt As String = String.Format("X: {0}, Y: {1}", CStr(DateVal), line.Values(i))
line.InteractivityStyles.Add(i, New NInteractivityStyle(tt))
Next

second :

ncwc:NChartControl
id="nChartControl1"
runat="server"
AjaxEnabled="True"
AsyncAutoRefreshEnabled="False"
AsyncCallbackTimeout="10000"
AsyncRequestWaitCursorEnabled="False"
OnQueryAjaxTools="nChartControl1_QueryAjaxTools">
ncwc:NChartControl>

Dim CH As NCartesianChart = NChartControl1.Charts(0)

Dim line As NLineSeries = CType(CH.Series(b), NLineSeries)

line.Values.AddRange(CType(yValues(b), ArrayList))
line.XValues.AddRange(CType(xValues(b), ArrayList))

For i As Integer = 0 To line.Values.Count - 1
Dim DateVal As DateTime = Convert.ToDateTime(line.XValues(i))
Dim tt As String = String.Format("X: {0}, Y: {1}", CStr(DateVal), line.Values(i))
line.InteractivityStyles.Add(i, New NInteractivityStyle(True, Nothing, tt))
Next

Protected Sub nChartControl1_QueryAjaxTools(ByVal sender As Object, ByVal e As EventArgs)
nChartControl1.AjaxTools.Add(New NAjaxTooltipTool(True))
End Sub


I hope anyone understand my problem and can help me, because in this Case the Tooltips are very important ...


thanks Marc

PS: sorry for my bad english



Similar Topics


Reading This Topic