This is a migrated thread and some comments may be shown as answers.

Obtaining the cartesian grid line annotation value exact based in mouse position

8 Answers 258 Views
ChartView
This is a migrated thread and some comments may be shown as answers.
Maurer
Top achievements
Rank 2
Maurer asked on 30 May 2017, 02:59 PM
Dear Support Team,

How we obtain the cartesian grid line annotation value exact based in mouse position  to plot vertical or horizontal grid line annotations using mouse click without insert the exact value manually?

Thanks in advance!

Best regards,

Henrique

8 Answers, 1 is accepted

Sort by
0
Maurer
Top achievements
Rank 2
answered on 30 May 2017, 03:03 PM
Other image 
0
Accepted
Dimitar
Telerik team
answered on 31 May 2017, 06:49 AM
Hi Maurer,

Here is how you can achieve this:
private void RadChartView1_MouseDown(object sender, MouseEventArgs e)
{
    var mousePos = e.Location.Y;
    var verticalAxis = radChartView1.Axes[1] as LinearAxis;
    double currentDistance = double.MaxValue;
    double minDistance = double.MaxValue;
    double value = double.NaN;
    double step = (verticalAxis.ActualRange.Maximum - verticalAxis.ActualRange.Minimum) / verticalAxis.Model.LayoutSlot.Height;
 
    for (double i = verticalAxis.ActualRange.Minimum; i < verticalAxis.ActualRange.Maximum; i += step)
    {
        var loc1 = verticalAxis.GetLocationOfValue(i) + radChartView1.View.Margin.Top;
 
        currentDistance = Math.Abs(loc1 - mousePos);
 
        if (currentDistance < minDistance)
        {
            minDistance = currentDistance;
        }
        else
        {
            value = i;
            break;
        }
 
    }
 
    CartesianGridLineAnnotation annotation1 = new CartesianGridLineAnnotation();
    annotation1.Axis = this.radChartView1.Axes[1] as CartesianAxis;
    annotation1.Value = value;
    annotation1.BorderColor = Color.Red;
    annotation1.BorderDashStyle = DashStyle.Solid;
    annotation1.BorderWidth = 1;
    this.radChartView1.Annotations.Add(annotation1);
}

I hope this will be useful. Let me know if you have additional questions.

Regards,
Dimitar
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Maurer
Top achievements
Rank 2
answered on 31 May 2017, 04:51 PM

Hi Dimitar,

Thank you very much for your support!

The first issue is about the 'RadChartView.Annotations.Add(annotationToAdd)' method ,
when we add annotations using this method to create vertical and horizontal annotations with one mouse click the vertical line is created but the position is incorrect,  the behavior is strange.

The same does not ocurres when we using 'RadChartView.Annotations.AddRange(annotations.ToArray())'.

Please see the attached images and the code below:

 

  private void RadChartView1_MouseDown(object sender, MouseEventArgs e)

        {
            CreateHorizontalAnnotation(e);

            CreateVerticalAnnotation(e);

            //1 Works correctly
            //radChartView1.Annotations.AddRange(annotations.ToArray());
        }
  
  
  #region Create Cartesian Annotations Methods

        private void CreateHorizontalAnnotation(MouseEventArgs e)
        {
            var mousePos = e.Location.Y;
            var verticalAxis = radChartView1.Axes[1] as LinearAxis;
            var minDistance = double.MaxValue;
            var value = double.NaN;
            var step = (verticalAxis.ActualRange.Maximum - verticalAxis.ActualRange.Minimum) / verticalAxis.Model.LayoutSlot.Height;

            for (var i = verticalAxis.ActualRange.Minimum; i < verticalAxis.ActualRange.Maximum; i += step)
            {
                var loc1 = verticalAxis.GetLocationOfValue(i) + radChartView1.View.Margin.Top;

                var currentDistance = Math.Abs(loc1 - mousePos);

                if (currentDistance < minDistance)
                {
                    minDistance = currentDistance;
                }
                else
                {
                    value = i;
                    break;
                }

            }

            var annotation1 = new CartesianGridLineAnnotation
            {
                Axis = radChartView1.Axes[1] as CartesianAxis,
                Value = value,
                BorderColor = Color.Red,
                BorderDashStyle = DashStyle.Solid,
                BorderWidth = 1
            };

            //1 Works correctly
            //annotations.Add(annotation1);

            //2 It doesn't work.
            this.radChartView1.Annotations.Add(annotation1);
        }

        private void CreateVerticalAnnotation(MouseEventArgs e)
        {
            var mousePos = e.Location.X;

            var horizontalAxis = radChartView1.Axes[0] as DateTimeContinuousAxis;

            DateTime? value = null;

            var referenceDate = horizontalAxis.ActualRange.Minimum;

            var referencePosition = mousePos;

            do
            {
                var loc1 = horizontalAxis.GetLocationOfValue(referenceDate) + radChartView1.View.Margin.Right;

                if (loc1 > referencePosition)
                    break;

                value = referenceDate;

                referenceDate = referenceDate.AddSeconds(1);

            } while (referenceDate <= horizontalAxis.ActualRange.Maximum);


            if (!value.HasValue)
                return;

            var annotation = new CartesianGridLineAnnotation
            {
                Axis = radChartView1.Axes[0] as DateTimeContinuousAxis,
                Value = value,
                BorderColor = Color.Blue,
                BorderDashStyle = DashStyle.Solid,
                BorderWidth = 1
            };

            //1 Works correctly
            //annotations.Add(annotation);

            //2 It doesn't work.
            this.radChartView1.Annotations.Add(annotation);
        }

        #endregion


I would like to know if my method to create the vertical line in mouse click position when the data is of type DateTimeContinuousAxis is correct or exist some the advice to this solution,

Can I use the mouse move event to automatically show the cartesian grid line annotation and display the values between the ticks in a label? Exists a advice about this question,

Thanks in advanced,
Henrique

0
Accepted
Dimitar
Telerik team
answered on 01 Jun 2017, 01:44 PM
Hi Henrique,

I was able to reproduce the observed behavior. It is caused because after adding of the chart elements are marked for update. This can be avoided by forcing the layout with the following code:
this.radChartView1.ChartElement.View.Layout();

Actually, there is a better way to calculate value:
private void RadChartView1_MouseDown(object sender, MouseEventArgs e)
{
    object hValue = this.GetVerticalAxisValueFromMouse(e);
    object vValue = this.GetHorizontalAxisValueFromMouse(e);
 
    CreateVerticalAnnotation(vValue);
    CreateHorizontalAnnotation(hValue);
}
 
private object GetVerticalAxisValueFromMouse(MouseEventArgs e)
{
    LinearAxis axis = radChartView1.Axes[1] as LinearAxis;
    double delta = axis.ActualRange.Maximum - axis.ActualRange.Minimum;           
    double totalHeight = axis.Model.LayoutSlot.Height;
    double ratio = 1 - (e.Location.Y - this.radChartView1.Area.View.Viewport.Y - axis.Model.LayoutSlot.Y) / totalHeight;
    double value = axis.ActualRange.Minimum + delta * ratio;
 
    return value;
}
 
private object GetHorizontalAxisValueFromMouse(MouseEventArgs e)
{
    DateTimeContinuousAxis axis = radChartView1.Axes[0] as DateTimeContinuousAxis;
    long delta = axis.ActualRange.Maximum.Ticks - axis.ActualRange.Minimum.Ticks;
    double totalWidth = axis.Model.LayoutSlot.Width;
    double ratio = (e.Location.X - this.radChartView1.View.Viewport.X - axis.Model.LayoutSlot.X) / totalWidth;
    double value = axis.ActualRange.Minimum.Ticks + delta * ratio;
 
    return new DateTime((long)value);
}
 
private void CreateHorizontalAnnotation(object value)
{
    var annotation = new CartesianGridLineAnnotation
    {
        Axis = radChartView1.Axes[1] as CartesianAxis,
        Value = value,
        BorderColor = Color.Red,
        BorderDashStyle = DashStyle.Solid,
        BorderWidth = 1
    };
 
    this.radChartView1.Annotations.Add(annotation);
}
 
private void CreateVerticalAnnotation(object value)
{
    var annotation = new CartesianGridLineAnnotation
    {
        Axis = radChartView1.Axes[0] as DateTimeContinuousAxis,
        Value = value,
        BorderColor = Color.Blue,
        BorderDashStyle = DashStyle.Solid,
        BorderWidth = 1
    };
 
    this.radChartView1.Annotations.Add(annotation);
}

I hope this will be useful.

Regards,
Dimitar
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Maurer
Top achievements
Rank 2
answered on 05 Jun 2017, 07:55 PM
Hi Dimitar,

Thank you very much for your support!

Best regards,
Henrique
0
Maurer
Top achievements
Rank 2
answered on 06 Jul 2017, 02:57 PM

Hi Dimitar,

The methods works ok but when the zoom is aplicatted the position does not correctly. How we get the exact position when i have zoom applied?

Thanks in advance!

Best regards,
Henrique

0
Hristo
Telerik team
answered on 07 Jul 2017, 11:03 AM
Hi Henrique,

Thank you for writing.

Indeed, the current zoom factors are not taken into consideration. You need to change the GetVerticalAxisValueFromMouse and GetHorizontalAxisValueFromMouse methods this way: 
private object GetVerticalAxisValueFromMouse(MouseEventArgs e)
{
    LinearAxis axis = radChartView1.Axes[1] as LinearAxis;
    IChartView view = (IChartView)axis.View;
 
    double delta = axis.ActualRange.Maximum - axis.ActualRange.Minimum;
    double totalHeight = axis.Model.LayoutSlot.Height;
    double ratio = 1 - (e.Location.Y - this.radChartView1.Area.View.Viewport.Y - view.PlotOriginY - axis.Model.LayoutSlot.Y) / (totalHeight * view.ZoomHeight);
    double value = axis.ActualRange.Minimum + delta * ratio;
 
    return value;
}
 
private object GetHorizontalAxisValueFromMouse(MouseEventArgs e)
{
    DateTimeContinuousAxis axis = radChartView1.Axes[0] as DateTimeContinuousAxis;
    IChartView view = (IChartView)axis.View;
 
    long delta = axis.ActualRange.Maximum.Ticks - axis.ActualRange.Minimum.Ticks;
    double totalWidth = axis.Model.LayoutSlot.Width;
    double ratio = (e.Location.X - this.radChartView1.View.Viewport.X - view.PlotOriginX - axis.Model.LayoutSlot.X) / (totalWidth * view.ZoomWidth);
    double value = axis.ActualRange.Minimum.Ticks + delta * ratio;
 
    return new DateTime((long)value);
}

I hope this helps. Should you have further questions please do not hesitate to write back.

Regards,
Hristo
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Maurer
Top achievements
Rank 2
answered on 07 Jul 2017, 06:07 PM

Hi Hristo

It worked!
Thank you very much for your support!

Best regards,

Henrique

Tags
ChartView
Asked by
Maurer
Top achievements
Rank 2
Answers by
Maurer
Top achievements
Rank 2
Dimitar
Telerik team
Hristo
Telerik team
Share this question
or