I've been working with Jeff LeProwse's AddXYZ+ applet to record GPS metadata with each point collected. I'm at the point where I'm in over my head as far as figuring out the coding.
I've set up ArcPad 10.2.2 to average 30 seconds of observations per point.
Problems with the script:
1. The applet uses onFeatureAdded which means the GPS metadata is recorded when OK is pressed to create the new point and not when the GPS finishes collecting the coordinates. So if you stand in the road for 30 seconds while the GPS collects the point and then move to the side of the road for 5 minutes filling in forms and press OK the GPS metadata is recorded for wherever you were standing at that moment, not out in the road.
2. For existing points the GPS metadata is updated onFeatureUpdated regardless of whether GPS is used to update the position. If the GPS is enabled and I move a point with the mouse the GPS metadata will update.
To get around this I've gone to calling the applet on GPS onAverageStop, which works when moving existing points, but doesn't for new points because there isn't an existing RecordSet to update(?) so I think populating the open EditForm is the way to go but can't get the code to work.
Summary: I'd like the script to record GPS metadata at the moment the GPS finishes averaging and records the position when adding new points with AddGPSPoint and moving existing points with MovePointToGPS only. Also needs to factor in the possibility of toggling between editing several point layers and a polyline layer with the QuickCapture toolbar.
Some code (which doesn't work):
<?xml version="1.0" encoding="UTF-8"?>
<ArcPad compiled="true">
<APPLET name="AddXYZ+_RCE_fields">
<SYSTEMOBJECTS>
<GPS onAverageStop="Call UpdateGPSFields"/>
</SYSTEMOBJECTS>
</APPLET>
<SCRIPT language="VBScript">Option Explicit
Sub UpdateGPSFields
'Define attributes
Dim MyCoordSys, objRS, f, strMessage, fCount, objForm, editPointLayer
'Get current edit point layer
Set editPointLayer = Map.EditLayer(1)
'Get current edit point layer EDITFORM
Set objForm = editPointLayer.Forms("EditForm")
'Check to see if the EDITFORM is open (3)
'If not open, assume Move to GPS operation on selected point
If objForm.Mode = 3 Then
Application.StatusBar.Text = "EDITFORM is open"
Else
'Get current coordinate system
Set MyCoordSys = Application.Map.CoordinateSystem
'Get the RecordSet of the currently selected feature's layer
'SelectionLayer returns layer of currently selected feature
Set objRS = Map.Selectionlayer.Records
'Bookmark the currently selected record
objRS.Bookmark = ThisEvent.Bookmark
'Check if the current shape is a point
If Right(objRS.Fields.ShapeType, 1) = 1 Then
'Check what the coordinate system is
If MyCoordSys.GeographicName = "GCS_WGS_1984" Then
'Loop through the current layer's fields
For Each f in objRS.Fields
Select Case Ucase(f.name)
Case "GPS_X"
f.Value = GPS.x
fCount = fCount + 1
Case "GPS_Y"
f.Value = GPS.y
fCount = fCount + 1
Case "GPS_LAT"
f.Value = GPS.Latitude
fCount = fCount + 1
...
Were you ever able to come up with a solution?
Have you thought about hitting a button to start the averaging, then another when ready to stop and also have it bring up the form. You could write the average location to an Application.UserProperties(“yourTempVariable”) until you finish your form, then write all to the shapefile (or whatever you are writing to). That is similar to how we mark an animal location from the plane, but allow the biologist to fill in the data afterwords. We are only collecting the one point, but they could be miles away before they have the form complete. I capture the point of the click, but you could do something similar with an average, I would assume. I also have a running average speed which is capture for 60 seconds “before” they hit the button….I’m not sure how easy it would be to do a running average of locations (also have many distance counters, some which reset based on other button action).
Thanks for the replies, I ended up rewriting the script so it checks if a form is open and if it is it writes the GPS data to a custom form page "GPS" which I'm adding to all my edit forms, otherwise it assumes I'm moving an existing point and uses the selected record approach. The code is really inefficient and I ran into some other issues but it's working at a basic level.
Rebecca's reply mentioning Application.UserProperties that I hadn't discovered yet gives me a whole other way to approach this that I'll attempt later when I have some time.
<?xml version="1.0" encoding="UTF-8"?>
<ArcPad compiled="true">
<APPLET name="GPS_Metadata2">
<SYSTEMOBJECTS>
<GPS onAverageStop="Call GPSMetadata"/>
</SYSTEMOBJECTS>
</APPLET>
<SCRIPT language="VBScript">
Option Explicit
Sub GPSMetadata
' Main routine to add GPS metadata from the NMEA string to edit layers configured with GPS attributes.
' Set variables
Dim editPointLayer, editLineLayer
'Get edit layers
Set editPointLayer = Map.EditLayer(1)
Set editLineLayer = Map.EditLayer(2)
'If there is an edit point layer, add/update GPS metadata if EDITFORM open or selected feature
If Not (editPointLayer Is Nothing) Then
' If the EDITFORM is open, assume creating a new point and fill in form and update GPS fields values
If editPointLayer.Forms("EDITFORM").Mode = 3 Then
Call FillGPSForm(editPointLayer)
' If EDITFORM is not open but the edit point layer has a feature currently selected update GPS fields values
ElseIf editPointLayer.Name = Map.SelectionLayer.Name Then
' Application.StatusBar.Text = "The edit point layer matches the selection layer"
Call UpdateGPSFields(editPointLayer)
End If
End If
'If there is an edit line layer, add/update GPS metadata if EDITFORM open or selected feature
If Not (editLineLayer Is Nothing) Then
' This won't work because form isn't open until after drawing a new polyline
If editLineLayer.Forms("EDITFORM").Mode = 3 Then
Call FillGPSForm(editLineLayer)
' If EDITFORM is not open but the edit line layer has a feature currently selected update GPS fields values
ElseIf edit LineLayer.Name = Map.SelectionLayer.Name Then
' Application.StatusBar.Text = "The edit line layer matches the selection layer"
Call UpdateGPSFields(editLineLayer)
End If
End If
End Sub
Sub FillGPSForm(editLayer)
' Populates GPS attributes values and the open form
' Use when creating a new feature and the EDITFORM is open
' Testing showed values not updating if attributes are on the active form page, hence the overkill with forms and values
' Define variables
Dim f, fCount
For Each f in editLayer.Forms("EDITFORM").Fields
Select Case Ucase(f.name)
Case "GPS_QUAL"
' Application.StatusBar.Text = GPS.Properties("QUALITY")
f.Value = GPS.Properties("QUALITY")
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_QUAL").Value = GPS.Properties("QUALITY")
fCount = fCount + 1
Case "GPS_SATS"
' Application.StatusBar.Text = GPS.Properties("SATS_USED")
f.Value = GPS.Properties("SATS_USED")
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_SATS").Value = GPS.Properties("SATS_USED")
fCount = fCount + 1
Case "GPS_X"
f.Value = GPS.x
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_X").Value = GPS.x
fCount = fCount + 1
Case "GPS_Y"
f.Value = GPS.y
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_Y").Value = GPS.y
fCount = fCount + 1
Case "GPS_Z"
f.Value = GPS.Z
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_Z").Value = GPS.Z
fCount = fCount + 1
Case "GPS_LAT"
f.Value = GPS.Latitude
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_LAT").Value = GPS.Latitude
fCount = fCount + 1
Case "GPS_LONG"
f.Value = GPS.Longitude
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_LONG").Value = GPS.Longitude
fCount = fCount + 1
Case "GPS_ALT"
f.Value = GPS.Altitude
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_ALT").Value = GPS.Altitude
fCount = fCount + 1
Case "GPS_PDOP"
f.Value = GPS.Properties("PDOP")
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_PDOP").Value = GPS.Properties("PDOP")
fCount = fCount + 1
Case "GPS_HDOP"
f.Value = GPS.Properties("HDOP")
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_HDOP").Value = GPS.Properties("HDOP")
fCount = fCount + 1
Case "GPS_VDOP"
f.Value = GPS.Properties("VDOP")
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_VDOP").Value = GPS.Properties("VDOP")
fCount = fCount + 1
Case "GPS_DGPS"
f.Value = GPS.Properties("DIFF_ID")
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_DGPS").Value = GPS.Properties("DIFF_ID")
fCount = fCount + 1
Case "GPS_DIFF"
f.Value = GPS.Properties("DIFF_AGE")
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_DIFF").Value = GPS.Properties("DIFF_AGE")
fCount = fCount + 1
Case "GPS_TIME"
f.Value = FormatDateTime(GPS.Properties ("UTC"), vbLongTime)
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_TIME").Value = FormatDateTime(GPS.Properties ("UTC"), vbLongTime)
fCount = fCount + 1
Case "GPS_DATE"
f.Value = FormatDateTime(GPS.Properties ("UTC"), vbShortDate)
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_DATE").Value = FormatDateTime(GPS.Properties ("UTC"), vbShortDate)
fCount = fCount + 1
Case "GPS_T_LOC"
f.Value = FormatDateTime(Now, vbLongTime)
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_T_LOC").Value = FormatDateTime(Now, vbLongTime)
fCount = fCount + 1
Case "GPS_D_LOC"
f.Value = FormatDateTime(Now, vbShortDate)
editLayer.Forms("EDITFORM").Pages.Item("GPS").Controls("txtGPS_D_LOC").Value = FormatDateTime(Now, vbShortDate)
fCount = fCount + 1
End Select
Next
End Sub
Sub UpdateGPSFields(selLayer)
' Updates GPS attributes for the selected editable feature
' Use when updating the position of an existing feature with GPS ("move to GPS")
' Define variables
Dim f, fCount, objRS
' Get the currently selected record from the edit layer
Set objRS = selLayer.Records
objRS.Bookmark = Map.SelectionBookmark
For Each f in objRS.Fields
Select Case Ucase(f.name)
Case "GPS_QUAL"
' Application.StatusBar.Text = GPS.Properties("QUALITY")
f.Value = GPS.Properties("QUALITY")
fCount = fCount + 1
Case "GPS_SATS"
' Application.StatusBar.Text = GPS.Properties("SATS_USED")
f.Value = GPS.Properties("SATS_USED")
fCount = fCount + 1
Case "GPS_X"
f.Value = GPS.x
fCount = fCount + 1
Case "GPS_Y"
f.Value = GPS.y
fCount = fCount + 1
Case "GPS_Z"
f.Value = GPS.Z
fCount = fCount + 1
Case "GPS_LAT"
f.Value = GPS.Latitude
fCount = fCount + 1
Case "GPS_LONG"
f.Value = GPS.Longitude
fCount = fCount + 1
Case "GPS_ALT"
f.Value = GPS.Altitude
fCount = fCount + 1
Case "GPS_PDOP"
f.Value = GPS.Properties("PDOP")
fCount = fCount + 1
Case "GPS_HDOP"
f.Value = GPS.Properties("HDOP")
fCount = fCount + 1
Case "GPS_VDOP"
f.Value = GPS.Properties("VDOP")
fCount = fCount + 1
Case "GPS_DGPS"
f.Value = GPS.Properties("DIFF_ID")
fCount = fCount + 1
Case "GPS_DIFF"
f.Value = GPS.Properties("DIFF_AGE")
fCount = fCount + 1
Case "GPS_TIME"
f.Value = FormatDateTime(GPS.Properties ("UTC"), vbLongTime)
fCount = fCount + 1
Case "GPS_DATE"
f.Value = FormatDateTime(GPS.Properties ("UTC"), vbShortDate)
fCount = fCount + 1
Case "GPS_T_LOC"
f.Value = FormatDateTime(Now, vbLongTime)
fCount = fCount + 1
Case "GPS_D_LOC"
f.Value = FormatDateTime(Now, vbShortDate)
fCount = fCount + 1
End Select
Next
' Update the record
objRS.Update
End Sub
</SCRIPT>
</ArcPad>
Mark, since you were able to resolve this yourself, you may want to close this thread by marking it "assumed answered".
But I've also attached one of my .vbs files for this project that has many of the functions I use to create and populate shapes on the fly (figuratively and literally, since it is an aerial survey). Reading thru this may give you some additional ideas. I actually have a set of four .vbs that I call from my .apa file (besides the .vbs for my form)
</APPLET> <SCRIPT src="sessionapps.vbs"/>
<SCRIPT src="transectapps.vbs"/>
<SCRIPT src="bearapps.vbs"/>
<SCRIPT src="createshapes.vbs"/>
</ArcPad>
I do this so I can easily separate the different functions for the arcpad session, and creating/populating lines vs point functions. I'll attach the createshapes.vbs in case it will help. I renamed it .txt to make it easier to access. Just fyi.