none
cursor position on chart RRS feed

  • Question

  • I have a chart with a line graph.

    If I write:

    Private Sub Chart1_MouseDown(sender As Object, e As MouseEventArgs) Handles Chart1.MouseDown

    x = Me.Chart1.ChartAreas(0).CursorX.Position
    y = Me.Chart1.ChartAreas(0).CursorY.Position

    end sub

    when i do mouse down i read x but y=NaN. Why this ?

    If I write:

    Private Sub Chart1_MouseDown(sender As Object, e As MouseEventArgs) Handles Chart1.MouseDown

    Me.Chart1.ChartAreas(0).CursorX.SetCursorPixelPosition(New PointF(e.X, e.Y), False)
    Me.Chart1.ChartAreas(0).CursorY.SetCursorPixelPosition(New PointF(e.X, e.Y), False)

    x = Me.Chart1.ChartAreas(0).CursorX.Position
    y = Me.Chart1.ChartAreas(0).CursorY.Position

    end sub

    whith mouse down i read x and y, but only integers. I need to read them as real numbers.

    Monday, February 10, 2020 11:22 PM

Answers

  • Hy again.

    Following picture shows 96 signals, each of 1024 points. They are each in a different series:

    The upgrading of the label with: N° of signal, y coordinate, is almost not working. Software used is that dealt in the preceding posts.

    The next picture shows exactely the same situation, but with a different software:

    You can see that it works perfectely.

    For doing this i had to do a pre-setting, in which I move the mouse at the top and then bottom of graph, then record position and save it:

    Private Sub Chart1_MouseMove(sender As Object, e As MouseEventArgs) Handles Chart1.MouseMove 
            
            Dim x, y As Single
    
            Me.Label4.Visible = True
            
            y = e.Y
            y = fattore_scala * Label_timewindow.Text * (y - graph_y_offset) / graph_height
            
            Me.Label4.Text = Format(y, "f")
    end sub

    Graph_height comes from bottom-top coordinates; graph_y_offset is top coordinate. My level of knowledge does not allow me more elegant (or complicated) solutions, but my goal has been reached.



    Wednesday, February 12, 2020 9:27 PM

All replies

  • Hi,

    I'm wondering what you want to get by Chart1.MouseDown event..
    If it is the mouse position, we can use e.Point (e.X and e.Y). 
      Dim x As Integer = e.X
      Dim y As Integer = e.Y

    The mouse position should be Integer, cannot be Single or Double. 
    Could you explain the meaning of "real numbers"? 

    Regards,

    Ashidacchi -- http://hokusosha.com

    Tuesday, February 11, 2020 2:44 AM
  • Hy Ashidacchi.

    It is not the mouse position that i would like to get, but the x,y coordinates of a chart.

    If for eample, axix x ranges from 0 to 1 and y from -100 to +100, clicking or passing over the chart I must get, in some point, (0.33, -74.8).

    Regards

    Tuesday, February 11, 2020 4:23 AM
  • In the Chart Control, the "cursor" is cross-hairs added at the mouse pointer location. I added the cursor lines to the example. But to get the mousemove event mouse pointer location we must convert the control pixels to chart coordinates. To get chart coordinates you get the mouse coordinates in control pixels and convert to chart axis coordinates as shown. The cursor lines are just an optional accessory we can add.

    See where PixelPositionToValue is used in the mousemove event to convert mouse pointer pixels to chart coordinates? See how the optional cursor red lines are added at the mouse pointer position? See the converted chart coordinates of the mouse position shown in the form titlebar?

     

                

     

    Imports System.Windows.Forms.DataVisualization.Charting
    Public Class Form1
        Private r As New Random
        Private PC As New CalloutAnnotation
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Chart1.Legends.Clear()
            Chart1.Series.Clear()
    
            Chart1.ChartAreas(0).AxisX.Minimum = -500
            Chart1.ChartAreas(0).AxisX.Maximum = 500
            Chart1.ChartAreas(0).AxisY.Minimum = -1200
            Chart1.ChartAreas(0).AxisY.Maximum = 1200
    
            Chart1.ChartAreas(0).AxisY.Interval = 300
            Chart1.ChartAreas(0).AxisX.Interval = 125
    
            Chart1.Series.Add("Series1")
            Chart1.Series("Series1").ChartType = SeriesChartType.FastLine
            Chart1.Series("Series1").BorderWidth = 0
    
            'just to add some random data points
            Dim v As Double = 400
            For i As Integer = -500 To 500
                v += r.Next(-50, 51)
                Chart1.Series("Series1").Points.AddXY(i, v)
            Next
    
        End Sub
    
        Private Sub Chart1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseMove
            Dim ht As DataVisualization.Charting.HitTestResult = Chart1.HitTest(e.X, e.Y)
            If Not ht.ChartElementType = ChartElementType.Nothing Then
                Dim xx As Double = ht.ChartArea.AxisX.PixelPositionToValue(e.X)
                Dim yy As Double = ht.ChartArea.AxisY.PixelPositionToValue(e.Y)
                If xx >= Chart1.ChartAreas(0).AxisX.Minimum And xx <= Chart1.ChartAreas(0).AxisX.Maximum And
                    yy >= Chart1.ChartAreas(0).AxisY.Minimum And yy <= Chart1.ChartAreas(0).AxisY.Maximum Then
    
                    Me.Chart1.ChartAreas(0).CursorX.SetCursorPixelPosition(New PointF(e.X, e.Y), False)
                    Me.Chart1.ChartAreas(0).CursorY.SetCursorPixelPosition(New PointF(e.X, e.Y), False)
                    Me.Text = xx.ToString & "   " & yy.ToString
    
                End If
            End If
        End Sub
    End Class


    PS we use the hit test to make sure we are over the chartarea not the titlebar or legend or something besides chart coordinates.


    Tuesday, February 11, 2020 9:28 AM
  • Hi,

    I might understand your requirement.
    I'd like to confirm type of your chart.
      (if it is a line chart, it would be difficult to click just on the line) 

    I hope you will provide a screenshot or share data of your chart via cloud storage such as OneDrive, Dropbox.

    Regards,


    Ashidacchi -- http://hokusosha.com

    Tuesday, February 11, 2020 9:49 AM
  • Hy everybody. I did in a similar way tommy2train said:

     Private Sub Chart1_MouseMove(sender As Object, e As MouseEventArgs) Handles Chart1.MouseMove
           
            Try
                Dim ht As DataVisualization.Charting.HitTestResult = Chart1.HitTest(e.X, e.Y)
                Dim xx As Double = ht.ChartArea.AxisX.PixelPositionToValue(e.X)
                Dim yy As Double = ht.ChartArea.AxisY.PixelPositionToValue(e.Y)
                Me.Label4.Visible = True     
                Me.Label4.Text = Format(yy, "f")
    
            Catch
                Me.Label4.Visible = False
                Application.DoEvents()           
            End Try
    
        End Sub
           

    You have to add the try...catch beacouse if mouse goes in some other part out of chart it makes error.

    This way, with many series of data on chart, label4 refreshing is very low, not usable.

    So I did in the simple way I did with Visual Basic 6 (that worked perfectly)

    Dim x, y As Single
            Me.Label4.Visible = True
            x = e.X
            y = e.Y
            y = y_axis_range * y / Me.Chart1.Height
            Me.Label4.Text = y

    In this way is very fast but I get an error, not large but error. Inner plot position has no offset, begins where the chart begins.

    If for example y scale is from 0 to 250, in some point instead of 100 i get  about 80. In this case y_axis_range=250.


    Tuesday, February 11, 2020 2:18 PM
  • Hy everybody. I did in a similar way tommy2train said:

     Private Sub Chart1_MouseMove(sender As Object, e As MouseEventArgs) Handles Chart1.MouseMove
           
            Try
                Dim ht As DataVisualization.Charting.HitTestResult = Chart1.HitTest(e.X, e.Y)
                Dim xx As Double = ht.ChartArea.AxisX.PixelPositionToValue(e.X)
                Dim yy As Double = ht.ChartArea.AxisY.PixelPositionToValue(e.Y)
                Me.Label4.Visible = True     
                Me.Label4.Text = Format(yy, "f")
    
            Catch
                Me.Label4.Visible = False
                Application.DoEvents()           
            End Try
    
        End Sub
           

    You have to add the try...catch beacouse if mouse goes in some other part out of chart it makes error.

    This way, with many series of data on chart, label4 refreshing is very low, not usable.

    So I did in the simple way I did with Visual Basic 6 (that worked perfectly)

    Dim x, y As Single
            Me.Label4.Visible = True
            x = e.X
            y = e.Y
            y = y_axis_range * y / Me.Chart1.Height
            Me.Label4.Text = y

    In this way is very fast but I get an error, not large but error. Inner plot position has no offset, begins where the chart begins.

    If for example y scale is from 0 to 250, in some point instead of 100 i get  about 80. In this case y_axis_range=250.


    Verg,

    "You have to add the try...catch beacouse if mouse goes in some other part out of chart it makes error."

    Use the hit test as the example shows. That is the only problem, you left that out?

    Each thing in the chart has its own area like title, grid axis etc. You must get the correct things.

     
    "with many series of data on chart, label4 refreshing is very low, not usable."

    All your code does is throw an error and do events that is why it is slow?

     

    "So I did in the simple way I did with Visual Basic 6 (that worked perfectly)

         y = y_axis_range * y / Me.Chart1.Height"

    You cant use the chart control client rectangle .height you need the chartarea height. The control clientrect includes all the titles and borders and many options etc. The chartarea? rect is where the chart scaling, axis settings are applied to the drawing. Look in the docs I gave you there are pictures of the areas.

    However if you just do it correctly the chart class methods work fine as shown in the example. There is no reason to do it yourself. There are more examples in the docs using the mouse.

    When you find yourself adding junk like do events and try catch to make it "work" you are normally just making a basic problem error worse.

    :)


    Tuesday, February 11, 2020 3:50 PM
  • tommy2train,

    i did not write the testing:

    If Not ht.ChartElementType = ChartElementType.Nothing Then ..........

    now it gives no error if you move outside the area.

    But if you have many series of data on chart (100), refreshing of coordinates is very slow. I do not understand relation with the number of series and speed.

    Yes, i have understood that y = y_axis_range * y / Me.Chart1.Height has the problem that the rectangle contains titles, scale etc.... , otherwise it would have been easy to do all the matter.

    So now the problem remains the very slow upgrading of coordinates.


    Tuesday, February 11, 2020 10:09 PM
  • tommy2train,

    i did not write the testing:

    If Not ht.ChartElementType = ChartElementType.Nothing Then ..........

    now it gives no error if you move outside the area.

    But if you have many series of data on chart (100), refreshing of coordinates is very slow. I do not understand relation with the number of series and speed.

    Yes, i have understood that y = y_axis_range * y / Me.Chart1.Height has the problem that the rectangle contains titles, scale etc.... , otherwise it would have been easy to do all the matter.

    So now the problem remains the very slow upgrading of coordinates.


    Verg,

    We cant help if we dont have an example to work from. You will need to make a complete working example and post it (like I do).

    It is probably something simple???

    How many points do you plot with each series? You can probably reduce to use about 50 pts for those curves. So only plot every 100th data point or something.

    I cant tell what the problem is. I have charts with 100,000 lines but only two series. I have 20 series maybe. Worked ok.

    You should be able to get it to work properly without goofy vb6 hacks like do events and on error resume next.

    Make a new simple reproducible one form example of the problem that we can copy from the forum and run.

    If you explain exactly what the charts are for, the purpose of them, perhaps it can all be done more simply? Perhaps you don't need 100 series and etc.

    You may need to make a timing loop and then you can remove code and see where you get speed improvements etc. optimize etc.

    But if you can make a simple reproducible example we can probably spot the bottle neck easily.

    PS Most of the time you will solve the problem yourself in making a new example for the forum.


    Wednesday, February 12, 2020 7:55 AM
  • Ok, give some time.

    If i fix i'll let everibody know what i've done.

    Regards

    Wednesday, February 12, 2020 8:54 AM
  • After many tests i have concluded that the slowness of label refreshing of y coordinate  (the only i need)  dos not depend on:

    number of series of data; with 1 series or 100 does not change

    It depends only on length of data (number of points). My chart is of "line" type.  

    If number of points is no more than 256, refreshing is acceptable, moving not fast mouse on grid coordinates follow. In fact,

    more length of data means more points on axis that mouse has to deal with.

    But 256 points correspond to low resolution. And what with display with better characteristics?

    Users need to look carefully  at signals acquired.

    The solution would be leaving the chart at its maximum resolution but changing the step of the mouse pointer, making it with less resolution.

    I repeat here the software that deals with the display of coordinates:

    Private Sub Chart1_MouseMove(sender As Object, e As MouseEventArgs) Handles Chart1.MouseMove      
            Dim ht As DataVisualization.Charting.HitTestResult = Chart1.HitTest(e.X, e.Y)
    
            If Not ht.ChartElementType = ChartElementType.Nothing Then
                Dim xx As Double = ht.ChartArea.AxisX.PixelPositionToValue(e.X)
                Dim yy As Double = ht.ChartArea.AxisY.PixelPositionToValue(e.Y)
                Me.Label4.Visible = True
                Me.Label4.Text = Format(yy, "f")
            end if    
    
    End Sub
    In the meanwhile i'm doing other tests.





    Wednesday, February 12, 2020 1:27 PM
  • After many tests i have concluded that the slowness of label refreshing of y coordinate  (the only i need)  dos not depend on:

    number of series of data; with 1 series or 100 does not change

    It depends only on length of data (number of points). My chart is of "line" type.  

    If number of points is no more than 256, refreshing is acceptable, moving not fast mouse on grid coordinates follow. In fact,

    more length of data means more points on axis that mouse has to deal with.

    But 256 points correspond to low resolution. And what with display with better characteristics?

    Users need to look carefully  at signals acquired.

    The solution would be leaving the chart at its maximum resolution but changing the step of the mouse pointer, making it with less resolution.

    I repeat here the software that deals with the display of coordinates:

    Private Sub Chart1_MouseMove(sender As Object, e As MouseEventArgs) Handles Chart1.MouseMove      
            Dim ht As DataVisualization.Charting.HitTestResult = Chart1.HitTest(e.X, e.Y)
    
            If Not ht.ChartElementType = ChartElementType.Nothing Then
                Dim xx As Double = ht.ChartArea.AxisX.PixelPositionToValue(e.X)
                Dim yy As Double = ht.ChartArea.AxisY.PixelPositionToValue(e.Y)
                Me.Label4.Visible = True
                Me.Label4.Text = Format(yy, "f")
            end if    
    
    End Sub
    In the meanwhile i'm doing other tests.





    Your finding is good but the example above does not have that problem?? Correct?

    You are saying it only takes one series with 256 points in your project to see a slowdown displaying the coordinates correct?

    But that does not happen with the example above?

    So there is something different between the example and your project.

    The example shown has 1000 pts in one series. I just ran it with 100000 points. The example works fine to show the coordinates. No slow down. Did you try it?

    So there is something else making your project slow.

    I cant reproduce the problem as far as I know. Where am I misunderstanding or ????


    Wednesday, February 12, 2020 2:02 PM
  • Hy tommy

    The software shown is that used in my application.

    Now I have done contradictory tests and i do not want to give wrong informations.

    I'll let you know when i'm sure.

    Regards


    Wednesday, February 12, 2020 3:34 PM
  • Hy again.

    Following picture shows 96 signals, each of 1024 points. They are each in a different series:

    The upgrading of the label with: N° of signal, y coordinate, is almost not working. Software used is that dealt in the preceding posts.

    The next picture shows exactely the same situation, but with a different software:

    You can see that it works perfectely.

    For doing this i had to do a pre-setting, in which I move the mouse at the top and then bottom of graph, then record position and save it:

    Private Sub Chart1_MouseMove(sender As Object, e As MouseEventArgs) Handles Chart1.MouseMove 
            
            Dim x, y As Single
    
            Me.Label4.Visible = True
            
            y = e.Y
            y = fattore_scala * Label_timewindow.Text * (y - graph_y_offset) / graph_height
            
            Me.Label4.Text = Format(y, "f")
    end sub

    Graph_height comes from bottom-top coordinates; graph_y_offset is top coordinate. My level of knowledge does not allow me more elegant (or complicated) solutions, but my goal has been reached.



    Wednesday, February 12, 2020 9:27 PM