Thursday, July 14, 2011

Programmatically Creating Session Graphics with Embedded Data

When drawing session graphics in GTViewer or GTVx, it is very simple to added embedded data. This is also true if you are using the GTDataObjects, the GTV .NET Controls, or GTCreate (but the syntax is slightly different than what I will show in this post).

Creating Session Graphics in GTViewer or GTVx uses a standard process. First set the Drawing Properties to your desired values, then draw the session graphics element (redline) with one of the Draw methods. The newly created session element will use the Drawing Properties you set.

There are two kinds of Drawing Properties that can be set. First, there are the Current Drawing Properties such as Filter Id, Color Id, Style Id, Weight, Fill, and Extended Style. These properties are set with methods like SetCurrentFilterId, SetCurrentColor, SetCurrentStyle, SetCurrentFill, and SetCurrentExtendedStyle. These properties will remember the value you set until you change them. So, you can set your filter id, color, and weight to specific values and all session elements that you create with the Draw methods will use these properties. You can also set these properties before each call to a Draw method if you choose (it will take slightly longer performance-wise if you set every property before each draw, but probably not enough to worry about).

Instance Drawing Properties are the second kind of Drawing Property. These properties will only be applied to the next session graphic created with a Draw method, then they reset themselves to a neutral state. There are really just two Instance Properties: Linkages and Embedded data. Linkages are two 32 bit integer keys on an element that will be automatically be used to look up records in the tabular data. Embedded Data is a string that is embedded on the session graphics element (and the data is available without going to the database and is also portable if you export the session graphics as a .gtg file).

Embedded Data has both a Type value and a string data value. Currently, the Embedded Data Type must always be set to 1. The Embedded Data String value can be any string value (size is not restricted, but their may be practical limits). However, if the string follows a specific format, it will be interpreted as tabular data and will work seamlessly with the Attribute Info functionality in GTViewer and GTVx. This format is called the \t\a\v format. Not a very catchy name, but it is what it is:

{\tTableName{\aAttrName\vValue}} 

You must have one record (table) specified with \t followed by the table name. You then need 1 or more attribute/value pairs where each pair is \a and the attribute’s name followed by \v and the value. In this format notation, the curly braces mean that that the enclosed portion can repeat, so you can have one or more attribute/values pair per table, and you can have one table or more tables. An example is shown below:

\tPole\aPole_Number\v1234\aHeight\v45\aClass\v1

Would represent:

Table: Pole

Attr 1: Pole_Number=1234

Attr 2: Height=45

Attr 3: Class=1

The following VB6 code is for GTViewer. It will create a filled circle in the center of your view and embed some data on it:

Dim cenX As Double
Dim cenY As Double

viewObj.GetViewCenter 1, cenX, cenY

docObj.SetCurrentFill True
docObj.SetCurrentFilterId 0
docObj.SetCurrentColor docObj.GetNearestColor(255, 0, 0)
docObj.DrawSetData 1, "\tMyTable1\aMyAttr1\vMyValue1\aMyAttr2\vmyValue2\tMyTable2\aMyAttr3\vMyValue3\aMyAttr4\vmyValue4"

docObj.DrawCircle32 1, cenX, cenY, 25

viewObj.RefreshView
This code is for GTViewer, but you can swap the viewObj and docObj with GTVX1 and it will work with GTVx as well. The embedded data contains two tables with two attributes on each table, so if you review the circle in GTViewer, it will show you something like this:

There are a few things to note in the above screenshots. First, the Red Drums on the tabs mean the data is Embedded Data and not retrieved from the database (they show as Blue Drums). The Table Names show on the tab. The first table name will show on the right mouse menu when you review one of the session graphics with embedded data. The Element tabs show the first few characters of the embedded data on the Embedded Data line.

The next example uses VB.NET and GTVx to illustrate something a little more realistic than the first example.

Imports GTVXLib
Imports System.Text


Public Class Form1

Dim docObj As AxGTVXLib.AxGTVX
Dim appObj As AxGTVXLib.AxGTVX
Dim viewObj As AxGTVXLib.AxGTVX

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

AxGTVX1.OpenFile("l:\electgasdemo\electgas.gtm")
AxGTVX1.SetHideRaster(1)

docObj = AxGTVX1
viewObj = AxGTVX1
appObj = AxGTVX1

End Sub


Private Sub ButtonPlaceMarker_Click(sender As System.Object, e As System.EventArgs) Handles ButtonPlaceMarker.Click

Dim cenX As Double
Dim cenY As Double

viewObj.GetViewCenter(1, cenX, cenY)

docObj.SetCurrentFill(True)
docObj.SetCurrentFilterId(0)
docObj.SetCurrentColor(docObj.GetNearestColor(255, 0, 0))

Dim data As New StringBuilder

data.Append("\t")
data.Append("Marker")
data.Append("\a")
data.Append("Time")
data.Append("\v")
data.Append(Now.ToLongTimeString)
data.Append("\a")
data.Append("Data")
data.Append("\v")
data.Append(Now.ToLongDateString)
data.Append("\a")
data.Append("User")
data.Append("\v")
data.Append(Environment.GetEnvironmentVariable("USERNAME"))

docObj.DrawSetData(1, data.ToString)

docObj.DrawCircle32(1, cenX, cenY, 25)

viewObj.RefreshView()

End Sub

End Class


The screenshots below show the demo app running after a marker has been placed followed by the Attribute Info dialog you get when reviewing the session graphics.





There are a few items to note in the above demo app. Again the DocObj and ViewObj are just used to simpify moving the code between GTViewer and GTVx. Since these objects are set to the AxGTVX1 object, the same code will work the same in GTVx and GTViewer. I used a StringBuilder to compose my embedded data. You can just as easily use a regular String instead. I think breaking the lines up with the StringBuilder makes it easier to read as well as being theoretically faster when running (versus just using the immutable String type). This example only uses one Table in the embedded data (the first example used 2).

I hope this helps to clarify using embedded data.

No comments: