|
caspernielsen -> PixelPositionToValue is BUGGED for logaritmic axes (5/10/2007 10:41:35 AM)
|
Hi After a whole day of experimenting with the PixelPositionToValue function I have come to the conclusion that it is bugged for usage in a webapplication. The reason is that it will now work properly until the end of the page cycle (where it cannot be used for anything). The reason I declare it bugged is that it gives different result on different stages of the lifecycle for the same input parameters. Following is my code that will demonstrate this, although some classes are not included, but I include the code here to exemplify the situation: In the m_Chart.PostPaint the "x" will have a correct value. in the m_Chart.PreRender the "x" will have an incorrect value (value here looks like the value should have been, had the x-axis not been logaritmic) This means calling the PixelPositionToValue function will only work properly in the PostPaint event handler, not before. This in effect means that we cannot use the pixel position to alter any content on our page, as it have already been streamed to the output buffer. Resolution: Make the PixelPositionToValue function function properly earlier in the page cycle. protected Measurement Source { get { if (ViewState["Source"] == null) { Random rand = new Random(); Measurement source = new Measurement(); for(int i = 0; i < Point.Frequencies.Length; i++) { source.Points = new Point(); source.Points.FrequencyType = (FrequencyType) i; source.Points.Intensity = rand.Next(140); } ViewState["Source"] = source; } return ViewState["Source"] as Measurement; } } protected override void OnInit(EventArgs e) { base.OnInit(e); m_Chart.Series[0].Points.DataBind(Source.Points, "Frequency", "Intensity", null); m_Chart.Click += new ImageClickEventHandler(Chart_Click); //m_Chart.PrePaint += new PaintEventHandler(Chart_PostPaint); m_Chart.PostPaint += new PaintEventHandler(Chart_PostPaint); m_Chart.PreRender += new EventHandler(Chart_PreRender); } void Chart_PreRender(object sender, EventArgs e) { if (!double.IsNaN(m_X) && !double.IsNaN(m_Y)) { double x = m_Chart.ChartAreas[0].AxisX.PixelPositionToValue(m_X); double y = m_Chart.ChartAreas[0].AxisY.PixelPositionToValue(m_Y); if (x > 0.0 && y > 0.0) { double nearestFrequency = GetNearestFrequency(m_Chart.Series[0], x, m_Chart.ChartAreas[0].AxisX.Logarithmic); m_Label.Text = "" + nearestFrequency; } } } void Chart_PostPaint(object sender, ChartPaintEventArgs e) { if (sender is ChartArea && !double.IsNaN(m_X) && !double.IsNaN(m_Y)) { double x = m_Chart.ChartAreas[0].AxisX.PixelPositionToValue(m_X); double y = m_Chart.ChartAreas[0].AxisY.PixelPositionToValue(m_Y); if (x > 0.0 && y > 0.0) { double nearestFrequency = GetNearestFrequency(m_Chart.Series[0], x, m_Chart.ChartAreas[0].AxisX.Logarithmic); m_Label.Text = "" + nearestFrequency; } } } private double GetNearestFrequency(Series series, double _x, bool isLogarithmic) { double x = isLogarithmic ? Math.Pow(10.0, _x) : _x; double ret = Point.Frequencies[0]; foreach(int frequency in Point.Frequencies) { if (Math.Abs(ret - x) > Math.Abs((double)frequency - x)) { ret = frequency; } } return ret; } double m_X = double.NaN; double m_Y = double.NaN; void Chart_Click(object sender, ImageClickEventArgs e) { if (e.X == 0 && e.Y == 0) { return; } HitTestResult hitTestResult = this.m_Chart.HitTest(e.X, e.Y); m_X = (double)e.X; m_Y = (double)e.Y; }
|
|
|
|