Hi,
following situation: I have a chart that contains multiple chart components. The x-Axis is time based and has a well known range. The values are not previously known and neither is the type of contained chart. So some are histogramcharts, some are linecharts, ..
At this point I wanted to retrieve the values that appear on the vertical axis of the current mouse position (i.e. chart 1 has at time X this value, chart 2 has at time X that value, ...). If there would be no value at this exact position, I could at all times linearily interpolate it with the two containing values to the left and to the right.
Now what I tried to accomplish it was:
* activate the cross hair* attach to the UltraChart.MouseMove event* calculate back the X position relative to the UltraChart component to the time based on the time range displayed and the width of the UltraChart* last but not least iterate over the chart components (stored in the UltraChart.Series property) and retrieve the value at the selected time
And here the problems:
* cross hair works fine* event is triggered, fine* the width of the UltraChart component does not match the UltraChart.Width property and there is no UltraChart.RenderWidth property; is there another property? The chart property tells me it is aroud 1600px, but truly is around 2200px if I move the mouse on it and output the position. Or is there some kind of scaling property that I need to include in my calculation?* under the assumption the calculation at point 3 worked and produced a valid result, would I really have to search linearly the two values I want using the UltraChart.Series property?
glad and happy for any kind of help,vazlav
prototype said:Is there a way to get the xAxis value (DateTime) a bit more accurate?
yes. you should use the axis Map and MapInverse functions.
these are only exposed through the FillSceneGraph event of the chart, so the way to reference the axes is a bit unusual, but it works. try this:
IAdvanceAxis XAxis { get; set; } IAdvanceAxis YAxis { get; set; } private void ultraChart1_FillSceneGraph(object sender, Infragistics.UltraChart.Shared.Events.FillSceneGraphEventArgs e) { this.XAxis = e.Grid["X"] as IAdvanceAxis; this.YAxis = e.Grid["Y"] as IAdvanceAxis; } private void ultraChart1_MouseMove(object sender, MouseEventArgs e) { if (this.XAxis == null || this.YAxis == null) { return; } object xValue = this.XAxis.MapInverse(e.X); object yValue = this.YAxis.MapInverse(e.Y); this.Text = xValue.ToString() + ", " + yValue.ToString(); }
I actually got it working slightly, but still the results are not exact enough due to the lacking calculation of the current timestamp (xPercentTime). This piece of code may help whoever reads this topic and want to try it out for himself. Is there a way to get the xAxis value (DateTime) a bit more accurate?
void Chart_MouseMove(object sender, MouseEventArgs e) { int leftBounds = 90; int rightBounds = 9; double xPos = e.Location.X - leftBounds; double width = chartPnl.Width - leftBounds - rightBounds; double xPercent = xPos / width; if ( xPercent >= 0 && xPercent <= 1) { DateTime xPercentTime = lastTimeAxisZoomFrom_ + TimeSpan.FromSeconds(((lastTimeAxisZoomTo_ - lastTimeAxisZoomFrom_).TotalSeconds * xPercent)); Dictionary<string, double> values = RetrieveValuesAt(xPercentTime); // do something with the values that were retrieved } } private Dictionary<string, double> RetrieveValuesAt(DateTime xPercentTime) { Dictionary<string, double> values = new Dictionary<string, double>(); if (chartDescription_.HasSeries) { foreach (ISeries series in chartDescription_.Series) { for (int i = 0; i < series.GetPoints().Count - 1; i++) { NumericTimeDataPoint point1 = series.GetPoints()[i] as NumericTimeDataPoint; NumericTimeDataPoint point2 = series.GetPoints()[i + 1] as NumericTimeDataPoint; if (point1 != null && point2 != null) { if (!point1.Empty && !point2.Empty) { if (point1.TimeValue <= xPercentTime && point2.TimeValue >= xPercentTime) { // linear interpolation TimeSpan xRange = point2.TimeValue - point1.TimeValue; double yRange = point2.NumericValue - point1.NumericValue; double k = (yRange) / xRange.TotalSeconds; double x = k * (xPercentTime - point1.TimeValue).TotalSeconds + point1.NumericValue; if (values.ContainsKey(series.Label)) { values.Remove(series.Label); } values.Add(series.Label, x); break; } } else { // no value at all } } else { IDataPoint pointA = series.GetPoints()[i]; if (pointA != null) { Console.WriteLine("--UNSUPPORTED pointA.type = {0}", pointA.GetType()); } } } } } return values; }