Page 1 of 1

Drawing line between two cursors?

Posted: Tue Oct 13, 2020 9:08 pm
by 16689453
I have two series on my chart, each with a cursor. Is there a way to draw a vertical line between the cursors to indicate the difference between the series values? (ideally, if I could display the value of the difference by the line that would be great).

Something like the yellow line here:
Untitled.png (6.55 KiB) Viewed 2341 times
Or is there another way to do this?

Re: Drawing line between two cursors?

Posted: Wed Oct 14, 2020 2:04 pm
by yeray

You should calculate the Interpolation points and draw the line manually. You could use the AnnotationTool to draw the difference value.
Here a simple example:

Code: Select all

Dim XPos, YVal1, YVal2 As Double
Private Sub Form_Load()  
  With TChart1
    .Aspect.View3D = False
    .Legend.Visible = False
    .Panel.Gradient.Visible = False
    .Panel.Color = vbWhite
    .Walls.Back.Gradient.Visible = False
    .Walls.Back.Color = vbWhite
    .Axis.Left.GridPen.Visible = False
    .Axis.Bottom.GridPen.Visible = False
    .AddSeries scFastLine
    .Series(0).FillSampleValues 25
    .AddSeries scFastLine
    .Series(1).FillSampleValues 25
    .Tools.Add tcAnnotate
  End With
  XPos = -1
End Sub

Function InterpolateSeries(ByVal SeriesIndex As Long, ByVal XValue As Double) As Double
    InterpolateSeries = InterpolateLineSeries(SeriesIndex, TChart1.Series(SeriesIndex).FirstValueIndex, TChart1.Series(SeriesIndex).LastValueIndex, XValue)
End Function

Function InterpolateLineSeries(ByVal SeriesIndex As Long, FirstIndex As Integer, LastIndex As Integer, XValue As Double) As Double
    Dim index As Integer
    Dim dx, dy, val As Double
    index = FirstIndex
    Do While ((TChart1.Series(SeriesIndex).XValues.Value(index) <= XValue) And (index < LastIndex))
      index = index + 1
    ' safeguard
    If (index < 1) Then
      index = 1
    ElseIf (index >= TChart1.Series(SeriesIndex).Count) Then
      index = TChart1.Series(SeriesIndex).Count - 1
    End If
    ' y=(y2-y1)/(x2-x1)*(x-x1)+y1
    dx = TChart1.Series(SeriesIndex).XValues.Value(index) - TChart1.Series(SeriesIndex).XValues.Value(index - 1)
    dy = TChart1.Series(SeriesIndex).YValues.Value(index) - TChart1.Series(SeriesIndex).YValues.Value(index - 1)
    If (dx <> 0) Then
      InterpolateLineSeries = dy * (XValue - TChart1.Series(SeriesIndex).XValues.Value(index - 1)) / dx + TChart1.Series(SeriesIndex).YValues.Value(index - 1)
      InterpolateLineSeries = 0
    End If
End Function

Private Sub TChart1_OnAfterDraw()
  With TChart1.Axis
    If XPos > -1 Then
      TChart1.Canvas.Pen.Style = psSolid
      TChart1.Canvas.Pen.Color = vbBlack
      TChart1.Canvas.DrawLine XPos, .Left.CalcYPosValue(YVal1), XPos, .Left.CalcYPosValue(YVal2)
    End If
  End With
End Sub

Private Sub TChart1_OnMouseMove(ByVal Shift As TeeChart.EShiftState, ByVal X As Long, ByVal Y As Long)
  XPos = X
  XVal = TChart1.Axis.Bottom.CalcPosPoint(XPos)
  YVal1 = InterpolateSeries(0, XVal)
  YVal2 = InterpolateSeries(1, XVal)
  TChart1.Tools.Items(0).asAnnotation.Text = Format$(YVal1 - YVal2, "#,##0.##")
  TChart1.Tools.Items(0).asAnnotation.Left = XPos + 5
  TChart1.Tools.Items(0).asAnnotation.Top = TChart1.Axis.Left.CalcYPosValue(YVal1) + (TChart1.Axis.Left.CalcYPosValue(YVal2) - TChart1.Axis.Left.CalcYPosValue(YVal1)) / 2
End Sub

Re: Drawing line between two cursors?

Posted: Fri Oct 16, 2020 12:20 am
by 16689453
Thanks Yeray - I used your example and it's working, up to a point.

If I want the line to follow the cursor (e.g., draw it in OnCursorToolChange), how do I erase the previous line before drawing the next one?
So far it just keeps drawing lines...

OK - I found I can remove the old lines by adding an m_Chart.Repaint() call - but that makes the update really jerky and erases the info when I stop moving the cursor. How can I help that?

Moving the m_Chart.Repaint() call - fixes the erasure on 'stop' problem. But the screen update is still super laggy

Re: Drawing line between two cursors?

Posted: Fri Oct 23, 2020 6:25 am
by yeray

It would help if you could arrange a simple example project to see what you are exactly doing.