Page 1 of 1

How to detect the collision between annotation and axis ?

Posted: Tue May 14, 2019 7:12 pm
by gurubikes
Hi,
I used the AnnotationXY function to show the annotation on selected series but I have an issue with it if the annotation is out of graphical area. See the picture. I must flip it vertically if hit on limit axis.
Annotation.png
Annotation.png (13.68 KiB) Viewed 6050 times
Thank you for helping

Gregory

Re: How to detect the collision between annotation and axis

Posted: Wed May 15, 2019 8:06 am
by Arction_LasseP
Hi,

One way to detect a collision between an annotation and an axis is to set the location of the annotation using AxisValuesBoudaries, and then compare the boundaries to axis ranges inside an event.

Setting the annotation to use AxisValuesBoundaries:

Code: Select all

AnnotationXY anno = new AnnotationXY(_chart.ViewXY, _chart.ViewXY.XAxes[0], _chart.ViewXY.YAxes[0]);
anno.Style = AnnotationStyle.Callout;
anno.TargetAxisValues.SetValues(4, 300); // Where the annotation points to
anno.Sizing = AnnotationXYSizing.AxisValuesBoundaries;
anno.AxisValuesBoundaries.SetValues(3.5, 4.2, 340, 400); // Set annotation size in axis values

_chart.ViewXY.Annotations.Add(anno);
The event can be for example RangeChanged, which triggers every time the minimum and/or maximum values of the corresponding axis are changed. In this example, every time Y axis range is changed, we check if the bottom or the top of the annotation hits the bottom or the top of the visible graph area. If this happens, the annotation is moved up or down.

Code: Select all

_chart.ViewXY.YAxes[0].RangeChanged += Axis_RangeChanged;

private void Axis_RangeChanged(object sender, RangeChangedEventArgs e)
        {
            if (_chart.ViewXY.YAxes[0].Minimum > _chart.ViewXY.Annotations[0].AxisValuesBoundaries.YMin)
            {
                _chart.ViewXY.Annotations[0].AxisValuesBoundaries.SetValues(3.5, 4.2, _chart.ViewXY.Annotations[0].AxisValuesBoundaries.YMin + 150, _chart.ViewXY.Annotations[0].AxisValuesBoundaries.YMax + 150);
            }
            else if (_chart.ViewXY.YAxes[0].Maximum < _chart.ViewXY.Annotations[0].AxisValuesBoundaries.YMax)
            {
                _chart.ViewXY.Annotations[0].AxisValuesBoundaries.SetValues(3.5, 4.2, _chart.ViewXY.Annotations[0].AxisValuesBoundaries.YMin - 150, _chart.ViewXY.Annotations[0].AxisValuesBoundaries.YMax - 150);
            }
        }
There are also other annotation properties, that can be useful in some cases. Setting KeepVisible true makes the annotation always stay inside the graph area, no matter how much the graph is moved.
Setting ClipInsideGraph to false allows the annotation to be drawn outside the axes. This can be combined with RenderBehindAxis, which controls if the annotation should be drawn over the axis ticks and labels.

Re: How to detect the collision between annotation and axis

Posted: Wed May 15, 2019 5:44 pm
by gurubikes
Hi,

Thank you for your support. This solution is not worked if I use dynamic annotation with tracking cursor. I now found the solution.

Gregory

Re: How to detect the collision between annotation and axis

Posted: Thu May 23, 2019 1:05 pm
by serhatc
gurubikes wrote:Hi,

Thank you for your support. This solution is not worked if I use dynamic annotation with tracking cursor. I now found the solution.

Gregory
hi gregory, i have same problem, how can you resolve it?

Re: How to detect the collision between annotation and axis

Posted: Fri May 24, 2019 1:58 pm
by gurubikes
Hi serhatc,

I use "Multi-channel tracking induvidually" demo with following modification :

Code: Select all

        
void pls_MouseClick(object sender, MouseEventArgs e)
        {
            MyChart.BeginUpdate();

            // Change previous series highlighting
            if (seriesBeingTracked != null)
                seriesBeingTracked.MouseHighlight = MouseOverHighlight.Simple;

            //Set series being tracked 
            seriesBeingTracked = (PointLineSeries)sender;
            seriesBeingTracked.MouseHighlight = MouseOverHighlight.None;

            //Set correct Y axis for value display 
            valueDisplay.AssignYAxisIndex = seriesBeingTracked.AssignYAxisIndex;

            //Change color for the value display
            valueDisplay.Fill.Color = ChartTools.CalcGradient(seriesBeingTracked.LineStyle.Color, Colors.White, 90);
            valueDisplay.Fill.GradientColor = ChartTools.CalcGradient(seriesBeingTracked.LineStyle.Color, Colors.White, 50);

            UpdateNearestValue(e);

            MyChart.EndUpdate();
        }

        void UpdateNearestValue(MouseEventArgs e)
        {
            MyChart.BeginUpdate();

            if (seriesBeingTracked != null)
            {
                double x;
                var position = e.GetPosition(MyChart);
                MyChart.ViewXY.XAxes[0].CoordToValue((int)position.X, out x, false);

                LineSeriesValueSolveResult res = seriesBeingTracked.SolveYValueAtXValue(x);
                if (res.SolveStatus == LineSeriesSolveStatus.OK)
                {
                    double nearestX = seriesBeingTracked.Points[res.NearestDataPointIndex].X;
                    double nearestY = seriesBeingTracked.Points[res.NearestDataPointIndex].Y;

                    valueDisplay.Visible = true;
                    valueDisplay.Text = "X: " + nearestX.ToString("0.0") + "\nY: " + nearestY.ToString("0.0");
                    valueDisplay.TargetAxisValues.SetValues(nearestX, nearestY);

                    double delta = MyChart.ViewXY.YAxes[seriesBeingTracked.AssignYAxisIndex].Maximum - MyChart.ViewXY.YAxes[seriesBeingTracked.AssignYAxisIndex].Minimum;
                    double ptY = MyChart.ViewXY.YAxes[seriesBeingTracked.AssignYAxisIndex].Maximum - nearestY;
                    double percentage = (ptY / delta) * 100;

                    if (percentage < 14 && percentage >= 0)
                    {
                        valueDisplay.LocationRelativeOffset = new PointFloatXY(0, 40);     // Show annotation below series.
                    }
                    else
                    {
                        valueDisplay.LocationRelativeOffset = new PointFloatXY(0, -40);     // Show annotation above series.
                    }
                }
                else
                {
                    valueDisplay.Visible = false;
                }
            }

            MyChart.EndUpdate();
        }