AdvancedHMI Software

General Category => Support Questions => Topic started by: MrPike on March 03, 2018, 10:06:43 AM

Title: Trend chart with events
Post by: MrPike on March 03, 2018, 10:06:43 AM
Archie, I am in need of your expertise again.  I'm starting a project using 3.99x communicating with a device over Modbus TCP.  I have added a built in windows chart and using it to trend some values with no problems.  The device has an event log comprised of 30 ASCII characters that I need to read(a different challenge).  What I would like to do is add an event from the log as text to the trend chart along the X axis area and mark it with either a vertical bar or red dot as shown in the attached pic.  I think I can read from the device with help from other posts but I cannot figure out how to add this event to the chart.  I hope this makes sense.  Basically I want to overlay the events on the trend to see the values when the event happened.  I don't even know how to start googling this for help:))  Thank you!
Title: Re: Trend chart with events
Post by: Archie on March 03, 2018, 11:00:26 AM
This can be done, but can get a little involved. I will start by giving you a code example:
Code: [Select]
   Private Sub Chart1PostPaint(ByVal sender As Object, ByVal e As System.Windows.Forms.DataVisualization.Charting.ChartPaintEventArgs)
        ' Make sure all series have been drawn before proceeding
         If Chart1 IsNot Nothing AndAlso Chart1.Visible Then
                      If ZPos >= 0 Then
                        Dim cg As System.Windows.Forms.DataVisualization.Charting.ChartGraphics = e.ChartGraphics
 
                        ' Get relative coordinates of the data point
                        Dim pos As System.Drawing.PointF = System.Drawing.PointF.Empty
                        Dim pos2 As System.Drawing.PointF = System.Drawing.PointF.Empty
 
                        pos.X = CSng(cg.GetPositionFromAxis("ChartArea1", System.Windows.Forms.DataVisualization.Charting.AxisName.X, ZPos))
                        '* Bottom of chart
                        pos.Y = CSng(cg.GetPositionFromAxis("ChartArea1", System.Windows.Forms.DataVisualization.Charting.AxisName.Y, 0))
                        '* Top of chart
                        pos2.Y = CSng(cg.GetPositionFromAxis("ChartArea1", System.Windows.Forms.DataVisualization.Charting.AxisName.Y, Chart1.ChartAreas(0).AxisY.Maximum))

                        '* Do not go beyond the charting area
                        If ZPos  >= Chart1.ChartAreas(0).AxisX.Minimum And ZPos <= Chart1.ChartAreas(0).AxisX.Maximum Then
                            ' Convert relative coordinates to absolute coordinates.
                            pos = cg.GetAbsolutePoint(pos)
                            pos2 = cg.GetAbsolutePoint(pos2)

                             ' Draw vertical position line in red
                            cg.Graphics.DrawLine(System.Drawing.Pens.Red, pos.X, pos2.Y, pos.X, pos.Y)
                        End If
                    End If
        End If
    End Sub

With ZPos being where you want the vertical line drawn.
Title: Re: Trend chart with events
Post by: MrPike on March 03, 2018, 11:59:01 PM
Archie, I hate to show my ignorance but I copied your code into my project and want to manually trigger it with a button for the moment while I test.  however I get this error and cannot proceed.  What am I doing wrong?  Thank you!
Title: Re: Trend chart with events
Post by: MrPike on March 04, 2018, 12:00:28 AM
forgot to add pic
Title: Re: Trend chart with events
Post by: Archie on March 04, 2018, 07:08:19 AM
Entirely my fault. I was missing an important part. The code is an event handler that automatically executes, but I left out the hook:

Code: [Select]
Private Sub Chart1PostPaint(ByVal sender As Object, ByVal e As System.Windows.Forms.DataVisualization.Charting.ChartPaintEventArgs) Handles Chart1.PostPaint
Title: Re: Trend chart with events
Post by: MrPike on March 05, 2018, 10:26:27 PM
Archie, I was able to manipulate your code and was successful in drawing a line and text at the point of my event trigger as shown on the attached.  However my next challenge is to create one for each event.  This code simply redraws the line and text at the location of the newest event.  How can I generate a line&text for each event? 

p.s.
In the attached pic, my event is a change of value of the green line.  Thank you
Title: Re: Trend chart with events
Post by: Archie on March 06, 2018, 07:37:47 AM
I have created a Chart extension control called ChartWithEvents. You can add this to your solution, then Build and you should have a ChartWithExtension in the Toolbox. This is part of the attached demo solution that shows how to use it.
Title: Re: Trend chart with events
Post by: MrPike on March 07, 2018, 12:20:20 AM
Thanks Archie.  I added the control to my toolbox and found the events region that does the necessary code.  In an attempt to avoid recreating the chart I already developed, I copied your code from the ChartsWithEvents.vb to my chart called Trend.  I have one snag that wont compile and selecting the recommended solution vb suggest(in pic) causes a ton of errors.  How can I get past this error?  thank you!!
Title: Re: Trend chart with events
Post by: Archie on March 07, 2018, 05:30:32 AM
If you are merging that code into your form, you do not want to change the inheritance. The form consists of 2 partial classes. When you changed the inheritance, it is telling you the two partial classes no longer match in their types.

A better technique would be to add the ChartWithEvents to your project, then change the type from a regular Chart to a ChartWithEvents in the designer class.

- In Solution Explorer, click the icon for Show All Files
- You can then expand down your form to see the hidden designer class
- Right click the designer class and select View Code
- Look for the declaration of the variable Chart1
- Change its type (after the AS) to ChartWithEvents (probably near the bottom of the file)
Code: [Select]
    Friend WithEvents Chart1 As ChartWithEvents
- Then change the chart creation to
Code: [Select]
        Me.Chart1 = New ChartWithEventsDemo.ChartWithEvents()
Title: Re: Trend chart with events
Post by: Godra on March 09, 2018, 08:48:39 PM
For those who might be interested, there is another way of adding vertical lines (in Annotation form), as explained here:

https://stackoverflow.com/questions/25801257/c-sharp-line-chart-how-to-create-vertical-line

The attached pictures shows how these vertical lines could possibly appear in Archie's new DataLoggerChart (http://advancedhmi.com/forum/index.php?topic=2034.0).

1st picture shows all applicable individual points as annotated (ex. 3 consecutive points have the same value and each point has annotation).
2nd picture shows the same with duplicates removed (ex. 3 consecutive points have the same value and only the first point has annotation).
Title: Re: Trend chart with events
Post by: MrPike on March 11, 2018, 12:05:14 PM
Very nice Godra.  How did you achieve the dashed vertical line?  I like this over my solid line because it covers my charted line, thanks. 
Title: Re: Trend chart with events
Post by: Godra on March 11, 2018, 01:40:12 PM
MrPike,

Take a look at this post: http://advancedhmi.com/forum/index.php?topic=2034.msg11445#new
Title: Re: Trend chart with events
Post by: MrPike on March 12, 2018, 11:05:45 PM
Archie, I almost have my project the way I want it except the string I write(which is my event) on the graph will update all previously drawn strings.  So what happens is the latest event now becomes the string that every event shows.  Obviously I would like to have each event show uniquely.  I just added a line of code to the ChartWithEvents.vb that you provided to draw the string.  Please see attached for reference and you will see all the events have the same text.  How can I get these to create a new String each time?  Thanks. 
Title: Re: Trend chart with events
Post by: MrPike on March 12, 2018, 11:07:15 PM
image did not attach first time.  Thx
Title: Re: Trend chart with events
Post by: MrPike on March 12, 2018, 11:08:43 PM
adding images one at a time
Title: Re: Trend chart with events
Post by: Archie on March 13, 2018, 02:55:20 AM
You will need a collection of strings to hold the description value for each event, just as done with the value collection.

My preferred method is to create a class that encapsulates the value and description string together. I updated my example program by adding an EventItem class. The new project is attached.

Godra's method of using annotations may be a cleaner or easier route. He showed the use of line annotations added to the chart, but I see there is also the option of adding text annotations. The annotation method lets you add the items, then let the chart handle the rendering.
Title: Re: Trend chart with events
Post by: MrPike on March 13, 2018, 09:06:01 PM
Thanks Archie, works like a champ.  I did try Godra's approach with annotations but I could not get the annotations to move with the graph since I use this as a "live" data chart.  The chart moves off the screen but the annotations stay in the same place.  I may have done something wrong but this method works well.  I very much appreciate the help.  My next struggle is to rotate the text to hopefully print diagonally to a void overlapping long strings.  Thank you.     
Title: Re: Trend chart with events
Post by: Godra on March 13, 2018, 09:28:26 PM
Just for the record, I just tried the chart from the other post with AUTO refresh and the annotation vertical lines did move as the graph was repainted.
Title: Re: Trend chart with events
Post by: MrPike on March 13, 2018, 09:39:11 PM
Thanks Godra, I'm sure I did something wrong.  I did not use your control directly but rather tried to mimic your code to avoid having to redo all my work.  I appreciate all your help!
Title: Re: Trend chart with events
Post by: MrPike on March 14, 2018, 02:38:44 PM
Archie, the last piece of my puzzle is to rotate the text of the event to print diagonally.  this would clean the chart up a lot and prevent overlapping on long strings.  However I cannot find the proper method to do this.  I have tried the drawstring.rotatetransform(45) but this seems to rotate the entire chart.  I cannot seem to pick out just the text from m_EventList(i).Description.  Is there a way to do this?  thank you.   
Title: Re: Trend chart with events
Post by: Archie on March 14, 2018, 03:20:23 PM
One method is to apply a matrix to the graphics object, draw the text, then apply a new matrix so it clears the transforms.

Based in my sample project, the code would look like this:
Code: [Select]
                       '* Add a description string if it exists
                        If Not String.IsNullOrEmpty(m_EventList(i).Description) Then
                            Dim m As New System.Drawing.Drawing2D.Matrix()
                            m.RotateAt(30, New PointF(pos.X, pos.Y))
                            cg.Graphics.Transform = m
                            cg.Graphics.DrawString(m_EventList(i).Description, Me.Font, New SolidBrush(Color.Red), pos.X, pos.Y + Font.Height)
                            cg.Graphics.Transform = New Drawing2D.Matrix
                        End If
Title: Re: Trend chart with events
Post by: MrPike on March 16, 2018, 11:20:52 PM
Works perfect Archie!  Can't thank you enough for the support.  Much appreciated!