Syntax Highlighing:
comments, key words, predefined symbols, class members & methods, functions & classes
# SOILDATA.sml
# Sample script for tutorial "Writing Scripts with SML".
# Demonstrates extracting attribute information from geospatial data, writing it to
# an external file, and launching that file in another application.
# Script processes a vector soil map to determine the soil types, the cumulative
# area for each soil type in acres, and creates a Comma-Separated Values (CSV)
# text file listing the soil symbol, acres, map unit identifier, and soil description.
# The input vector must have polygons and a polygon database table "MAPUNIT".
clear();
numeric i; # loop counter
# get the input vector object
class RVC_VECTOR SoilVec;
GetInputVector(SoilVec);
### check that this is an appropriate vector object for this script
if (SoilVec.$Info.NumPolys == 0) # check that the vector has polygons
{
PopupMessage("Vector must contain polygon elements to use this script. Exiting script.");
Exit();
}
# check if polygon table "MAPUNIT" exists.
class RVC_DBASE_POLYGON polyDB;
polyDB.OpenAsSubobject(SoilVec, "Read");
if (polyDB.IsTableValid("MAPUNIT") == 0 )
{
PopupMessage("Selected vector must include a polygon table named 'MAPUNIT'. Exiting now.");
Exit();
}
# check if POLYSTATS table exists; if not, make one.
if (polyDB.IsTableValid("POLYSTATS") == 0 )
{
VectorToolkitInit(SoilVec);
VectorUpdateStdAttributes(SoilVec);
}
# prompt user for name of output CSV file; open file and write header line
class STRING dfltName$ = _context.ScriptDir + "/outfile";
class STRING outfileName$ = GetOutputFileName(dfltName$, "Choose output CSV file:", "csv");
class FILE outfile = fopen(outfileName$, "w");
fprint(outfile, "musym,acres,muid,muname");
numeric polyarea; # area of current polygon from POLYSTATS table
numeric polynumHash[]; # hash to store element number of first polygon for each soil type
numeric soilAreaHash[]; # hash to store areas for different soil types
class STRING soilkey$; # key to hash entries
class STRINGLIST keylist; # list of soil types (keys) gotten from soilAreaHash
# loop through soil polygons to get areas from POLYSTATS table;
# use HASH to keep track of soil types and sum areas for polygons of same soil type
for i = 1 to SoilVec.$Info.NumPolys
{
soilkey$ = SoilVec.Poly[i].MAPUNIT.musym$;
polyarea = SoilVec.Poly[i].POLYSTATS.Area;
# add area of current polygon to value already stored in soil area hash for that soil;
# new keys are added automatically to the hash; ignore water polygons with no record in MAPUNIT table
if (soilkey$ <> "") then
soilAreaHash[soilkey$] += polyarea;
}
# get list of soilAreaHash keys as a stringlist to loop through them, and sort alphabetically
keylist = soilAreaHash.GetKeys();
keylist.Sort();
numeric areaScale = GetUnitConvArea("square meters", "acres"); # scale for converting areas to acres
class STRING musym$, muid$, muname$;
numeric recordnum;
# get old-style table info for the MAPUNIT table for record search
class DBTABLEINFO mapunitTbl;
mapunitTbl = TableGetInfo(SoilVec.poly.MAPUNIT);
# 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$] * areaScale; # get area for soil type and convert to acres
# get muid and soil name from field in MAPUNIT table
recordnum = TableKeyFieldLookup(mapunitTbl, "musym", musym$);
muid$ = SoilVec.Poly.MAPUNIT[recordnum].muid$;
# the numname values contain commas, so must be enclosed in double quotes for use in CSV file
muname$ = "\"" + SoilVec.Poly.MAPUNIT[recordnum].muname$ + "\"";
# write values to a line in the output CSV file
fprintf(outfile, "%s,%.2f,%s,%s\n", musym$, polyarea, muid$, muname$);
}
# close the output CSV file and open it in registered spreadsheet program
CloseVector(SoilVec);
fclose(outfile);
RunAssociatedApplication(outfileName$);
print("Done.");