Syntax Highlighing:
comments, key words, predefined symbols, class members & methods, functions & classes
# Soil_Info.sml
# Randy Smith, MicroImages, Inc.
# 28 September 2007
# View ToolScript
# Revised 30 June 2008
# Requires version 2007:74 of the TNT products
########################################################
#
# Tool Script for use with a Group or Layout that includes a vector soil map with a standard
# SSURGO soil database provided by the Natural Resource Conservation Service.
# Specificially, the polygon database must include a table named "mapunit".
#
# The tool script provides a polygon tool to allow the user to outline a desired area of
# the soil vector in the View. The soil vector layer must be the active layer
# in the active group when the tool is in use.
#
# The tool determines the soil types within this area, the cumulative area for each soil type
# within the area, and creates a CSV (Comma-Separated Values) text file containing a list
# of soil types, their areas, soil name, and soil kind. The CSV file is then used to open and
# run the application software that is associated with the CSV file type on the user's computer.
#
# This sample script can be modified to work with other types of vector data or with soil vector
# objects containing a different database structure.
#
##############################################################
#
# The following symbols are predefined
# class GRE_VIEW View {use to access the view the tool script is attached to}
# class GRE_GROUP Group {use to access the group being viewed if the script is run from a group view}
# class GRE_LAYOUT Layout {use to access the layout being viewed if the script is run from a layout view}
# numeric ToolIsActive Will be 0 if tool is inactive or 1 if tool is active
#
# The following values are also predefined and are valid when the various On...()
# functions are called which deal with pointer and keyboard events.
# numeric PointerX Pointer X coordinate within view in pixels
# numeric PointerY Pointer Y coordinate within view in pixels
# numeric ShiftPressed 1 if <shift> key being pressed or 0 if not
# numeric CtrlPressed 1 if <ctrl> key being pressed or 0 if not
# numeric LeftButtonPressed 1 if left pointer button pressed or 0 if not
# numeric RightButtonPressed 1 if right pointer button pressed or 0 if not
# numeric MiddleButtonPressed 1 if middle pointer button pressed or 0 if not
#
# The following script functions will be called (if used in the script) when
# the appropriate action or event occurs as described in the comments before each.
# To use a function, uncomment the lines containing the 'func' definition
# and ending brace '}' by removing the leftmost '#' on the line and add the
# function code between the two lines.
### Declarations of global variables
class GRE_GROUP aGroup; # use non-predefined class instance to handle use with Layouts
class GRE_LAYER_VECTOR soilLayer; # the layer containing the soil vector object
class RVC_VECTOR soilVec; # the soil vector object
#class MDISPREGIONTOOL tool; # class instance for the polygon tool that returns a region
class GUI_GADGET_POLYLINE tool; # polyline/polygon tool
numeric areaScale = GetUnitConvArea("square meters", "acres"); # scale for converting areas to acres
#######################################################
# function to check active layer to see if it is valid for use with tool.
func checkLayer () {
local numeric valid = false;
local numeric i;
local string tblName$;
local class RVC_DBASE_POLYGON polyRVC_DB;
if (aGroup.ActiveLayer.TypeID == "") # check for empty group
View.SetMessage("Group has no layers!");
else if (aGroup.ActiveLayer.TypeID == "Vector") { # check that active layer is a vector
soilLayer = aGroup.ActiveLayer;
DispGetVectorFromLayer(soilVec, soilLayer);
if (soilVec.$Info.NumPolys == 0) # check that the vector has polygons
View.SetMessage("Vector must contain polygon elements to use this tool!");
else { # check if polygon table "mapunit" exists.
polyRVC_DB.OpenAsSubobject(soilVec, "Read");
if (polyRVC_DB.IsTableValid(mapunit) ) { # mapunit table exists
valid = true;
View.SetMessage("Vector is valid.");
}
else # no mapunit table
View.SetMessage("Active layer vector object must include a polygon table named 'mapunit'!");
}
}
else # active layer is not a vector object
View.SetMessage("Active layer must be a vector object to use this tool!.");
return valid;
}
##############################################
# Callback for when the active layer changes.
proc cbLayer() {
checkLayer();
}
###############################################
# Callback for when the active group changes.
proc cbGroup() {
aGroup = Layout.ActiveGroup;
WidgetAddCallback(aGroup.LayerSelectedCallback, cbLayer);
cbLayer();
}
########################################################
# Called when user presses 'right' pointer/mouse button.
proc OnRightButtonPress () {
if ( checkLayer() ) {
local class REGION2D toolRegion; # region gotten from tool and transformed to map coordinates
local class RVC_GEOREFERENCE vGeoref; # default georeference for the soil vector object
local class RVC_VECTOR regionVec, xSoilVec;
local numeric i; # loop counter
local numeric polyarea; # area of polygon from Polystats table.
local string key$; # key to hash entries
local numeric soilAreaHash[]; # hash to store areas for different soil types
local numeric polyNumHash[]; # hash to store element number of first polygon for each soil type
local numeric polynum; # polygon element number
local class STRINGLIST keyList; # list of soil types (keys) gotten from hash
local string musym$, muname$, mukind$; # values to be written as formatted text to CSV file
local class FILE outfile; # handle for open text file
local string dfltName$ = _context.ScriptDir + "/outfile.csv";
local string outfileName$; # name of output CSV file
# get the georeference for the soil vector
soilVec.GetDefaultGeoref(vGeoref);
# region created by tool has screen coordinates;
# must translate to map coordinates of the view (view coordinates) and
# then to map coordinates of the vector object in the active layer.
toolRegion = RegionTrans(tool.Region, View.GetTransViewToScreen(1)); # inverse, screen to view
toolRegion = RegionTrans(toolRegion, View.GetTransMapToView(vGeoref.GetCoordRefSys(), 1) ); # inverse, view to map
# convert region to temporary vector object to use for extraction
CreateTempVector(regionVec);
regionVec = ConvertRegionToVect(toolRegion);
View.SetMessage("Extracting area...");
# extract the area of the soil vector object to a temporary vector for processing
CreateTempVector(xSoilVec);
xSoilVec = VectorExtract(regionVec, soilVec, "InsideClip", "AddBorder,RemExRecords");
CloseVector(regionVec);
View.SetMessage("Making CSV file...");
# prompt user for name of output CSV file; open file and write header line
outfileName$ = GetOutputFileName(dfltName$, "Choose output CSV file:", "csv");
outfile = fopen(outfileName$, "w");
fprint(outfile, "musym,acres,muname,mukind");
# loop through extracted polygons to get areas from POLYSTATS table;
# use HASH to keep track of soil types and add areas for polygons of same type
for i = 1 to xSoilVec.$Info.NumPolys {
key$ = xSoilVec.Poly[i].mapunit.musym$;
polyarea = xSoilVec.Poly[i].POLYSTATS.Area;
if (soilAreaHash.Exists(key$) ) { # soil type is already in the soil area hash
# add area of current polygon to value already stored in soil area hash for that soil
soilAreaHash[key$] = soilAreaHash[key$] + polyarea;
}
else { # new soil type
soilAreaHash[key$] = polyarea; # assign area of polygon to soil area hash key
polyNumHash[key$] = i; # assign element number of polygon to polynum hash key
}
}
# get list of hash keys as a stringlist to loop through them
keylist = soilAreaHash.GetKeys();
# loop through keys by numeric position in stringlist (starting with 0)
for i = 0 to keylist.GetNumItems() - 1 {
musym$ = keylist.GetString(i); # soil identifier
polyarea = soilAreaHash[musym$]; # area for soil type
polyarea = polyarea * areaScale; # convert area from square meters to acres
# get soil name and kind from fields in mapunit table using polygon numbers stored in polynum hash
polynum = polyNumHash[musym$];
muname$ = "\"" +xSoilVec.Poly[polynum].mapunit.muname$ + "\""; # field contains commas, so must be quoted for use in CSV file
mukind$ = xSoilVec.Poly[polynum].mapunit.mukind$;
# write values to a line in the output CSV file
fprintf(outfile, "%s,%.2f,%s,%s\n", musym$, polyarea, muname$, mukind$);
}
View.SetMessage("Done.");
fclose(outfile);
RunAssociatedApplication(outfileName$); # launch application associated with the CSV file type (e.g. Excel)
CloseVector(xSoilVec);
}
} # end of OnRightButtonPress
# Called the first time the tool is activated.
# If the tool implements a dialog it should be created (but not displayed) here.
proc OnInitialize () {
if (Layout) {
WidgetAddCallback(Layout.GroupSelectedCallback, cbGroup);
aGroup = Layout.ActiveGroup;
}
else
aGroup = Group;
WidgetAddCallback(aGroup.LayerSelectedCallback, cbLayer);
# Create polygon tool.
tool = ViewCreatePolygonTool(View);
ToolAddCallback(tool.ApplyCallback, OnRightButtonPress);
} # end of OnInitialize
# Called when tool is to be destroyed, will not be called if tool was never activated.
# If the tool implements a dialog it should be destroyed here.
proc OnDestroy () {
tool.Managed = 0;
} # end of OnDestroy
# Called when tool is activated.
# If the tool implements a dialog it should be "managed" (displayed) here.
proc OnActivate () {
tool.Managed = 1;
tool.HasPosition = 0;
} # end of OnActivate
# Called when tool is deactivated (usually when switching to another tool).
# If the tool implements a dialog it should be "unmanaged" (hidden) here.
proc OnDeactivate () {
tool.Managed = 0;
} # end of OnDeactivate
# Called when tool is to be 'suspended' during a redraw operation.
# proc OnSuspend () {
# } # end of OnSuspend
# Called when tool is to be 'resumed' after a redraw operation.
# If the tool displays any graphics they should be updated by this function.
# proc OnResume () {
# } # end of OnResume
# Called when user presses 'left' pointer/mouse button.
# proc OnLeftButtonPress () {
# } # end of OnLeftButtonPress
# Called when user presses 'middle' pointer/mouse button.
# proc OnMiddleButtonPress () {
# } # end of OnMiddleButtonPress
# Called when user releases 'left' pointer/mouse button.
# proc OnLeftButtonRelease () {
# } # end of OnLeftButtonRelease
# Called when user releases 'right' pointer/mouse button.
# proc OnRightButtonRelease () {
# } # end of OnRightButtonRelease
# Called when user releases 'middle' pointer/mouse button.
# proc OnMiddleButtonRelease () {
# } # end of OnMiddleButtonRelease
# Called when user moves cursor if no button being pressed
# proc OnPointerMoveNoButton () {
# } # end of OnPointerMoveNoButton
# Called when user moves cursor while holding down button
# proc OnPointerMoveWithButton () {
# } # end of OnPointerMoveWithButton
# Called when cursor enters window associated with view.
# proc OnEnterWindow () {
# } # end of OnEnterWindow
# Called when cursor leaves window associated with view.
# proc OnLeaveWindow () {
# } # end of OnLeaveWindow
# Called when user presses 'key' on keyboard.
# proc OnKeyPress (key) {
# } # end of OnKeyPress