Soil_Info.sml

  Download

More scripts: Display Toolbar

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