Syntax Highlighing:
comments, key words, predefined symbols, class members & methods, functions & classes
# DB_WRITE2.SML
# Sample script for tutorial "Writing Scripts with SML".
# Illustrates creating database table, fields,
# and attaching records using RVC_DATABASE classes and methods.
# version 21 July 2014
# Script uses vector object CBSOILS_Lite as input. It creates
# an output vector with a point at the centroid position of
# each soil polygon in the input. These points are attributed
# with selected values from the input Class, DESCRIPTN, and
# YIELD tables.
# Some records in the input CBSOILS_Lite Class table are attached
# to multiple polygons; there are no duplicate records in the Class table.
# The script maintains this structure in the output vector by iterating
# through the records in the input Class table to get the
# desired attribute from this table and from related records
# in the other input tables, and creating a record in the output
# vector point database with these values. For each Class
# record the script also gets the list of attached soil polygons
# and iterates through these to create a corresponding centroid
# point in the output vector and attach the current soil data record
# to it.
### Declarations
class RVC_VECTOR VectIn, VectOut;
class STRING prompt$;
clear();
### Get input vector object with polygons.
prompt$ = "Select / CB_DATA / CB_SOILS.RVC / CBSOILS_Lite.";
class RVC_OBJITEM vectInObjItem;
DlgGetObject(prompt$, "Vector", vectInObjItem, "ExistingOnly");
VectIn.Open(vectInObjItem, "Read");
### Get georeference parameters for input vector.
class RVC_GEOREFERENCE georefV;
VectIn.GetDefaultGeoref(georefV);
printf("VectIn Coordinate Reference System = %s\n", georefV.GetCoordRefSys().Name);
### Get transformation from object to map coordinates for the input vector
class TRANS2D_MAPGEN transObjToMap;
georefV.GetTransParm(transObjToMap, 0, georefV.GetCalibModel() );
# structure for name and description of object; will reuse this for opening
# tables in input vector and in creating output georeference, database, and tables
class RVC_DESCRIPTOR descriptor;
### Open input vector polygon database
class RVC_DBASE_POLYGON polyDB;
polyDB.OpenAsSubobject(VectIn, "Read");
# open the "CLASS" polygon table
descriptor.SetName("CLASS");
class RVC_DBTABLE classTbl;
classTbl.Open(polyDB, descriptor, "Read");
# open the "DESCRIPTN" polygon table
descriptor.SetName("DESCRIPTN");
class RVC_DBTABLE descriptnTbl;
descriptnTbl.Open(polyDB, descriptor, "Read");
# open the "YIELD" polygon table
descriptor.SetName("YIELD");
class RVC_DBTABLE yieldTbl;
yieldTbl.Open(polyDB, descriptor, "Read");
# open the "POLYSTATS" polygon table
descriptor.SetName("POLYSTATS");
class RVC_DBTABLE polystatsTbl;
polystatsTbl.Open(polyDB, descriptor, "Read");
### Get new output vector object initialized for use with
### with the Vector Toolkit, and create implied
### georeference using parameters from input vector.
prompt$ = "Select new vector object for output.";
GetOutputVector(VectOut, "VectorToolkit,Planar");
# set name and description for a georeference subobject of the output vector
#class RVC_DESCRIPTOR descriptor;
descriptor.SetName("Georeference");
descriptor.SetDescription( sprintf("Implied georeference to %s", georefV.GetCoordRefSys().Name) );
# set up georeference for the output vector
class RVC_GEOREFERENCE georefOut;
georefOut.SetCoordRefSys(georefV.GetCoordRefSys() );
georefOut.SetImplied();
georefOut.Make(VectOut, descriptor);
printf("VectOut Coordinate Reference System = %s\n", georefOut.GetCoordRefSys().Name);
# Create point database for VectOut.
class RVC_DBASE_POINT pointDB;
pointDB.OpenAsSubobject(VectOut, "Write"); # this method creates the database if it doesn't already exist
# variables for setting up the "SoilTypes" table in point database.
class RVC_DBTABLE soilTypeTbl; # handle for the table
class RVC_DBFIELDINFO fieldinfo[3]; # array of field info class instances
# set up desriptor for the new table
descriptor.SetName("SoilTypes");
descriptor.SetDescription("Table created by SML script.");
# set up the "SYMBOL" field parameters
fieldinfo[1].SetName("SYMBOL");
fieldinfo[1].SetType("String");
fieldinfo[1].SetFlag("PrimaryKey");
fieldinfo[1].SetDispWidth(6);
# set up the "SOIL" field parameters
fieldinfo[2].SetName("SOIL");
fieldinfo[2].SetType("String");
fieldinfo[2].SetDispWidth(90);
# set up the "WHEAT_YLD" field parameters
fieldinfo[3].SetName("WHEAT_YLD");
fieldinfo[3].SetType("UByte"); # unsigned 1-byte (8-bit) integer, 0 to 255 range
fieldinfo[3].SetDispWidth(9);
# set up the MakeParms for making the SoilTypes table
class RVC_DBTABLE_MAKEPARMS stParms(fieldinfo, "OneRecordPerElement", "UTF8");
# create the SoilTypes table in the point database with the above parameters
soilTypeTbl.Make(pointDB, descriptor, stParms);
### Variables for reading polygon attributes and creating and attaching output point
### database record
numeric recordnum; # record number created by TableNewRecord() function call
numeric i, j; # counters for processing loop
class RVC_RECORDNUM recNumClass; # structure for a record number from polygon CLASS table
class RVC_RECORDNUM recNumList[10]; # array of record numbers for related records from DESCRIPTN and YIELD tables
class RVC_RECORDNUM recNumPolystats[10]; # array of record numbers for related records from polygon POLYSTATS table
class RVC_DBTABLE_RECORD classRecord; # current record from polygon CLASS table
class RVC_DBTABLE_RECORD record; # current record from the DESCRIPTN or YIELD table
class RVC_ELEMENT elemlist[50]; # array of polygons attached to current CLASS table record
numeric numAttached; # number of polygons attached to current CLASS table record
numeric numRelated; # number of records in DESCRIPTN or YIELD table related to current CLASS record
class STRING symbol$; # value for Class field in CLASS table
class STRING name$; # value for Name field in DESCRIPTN table
numeric wheatnum; # value for WHEAT field in YIELD table
class POINT2D pt; # coordinates of the polygon centroid
numeric pointnum; # counter for number of points added to outut vector
class RVC_DBTABLE_RECORD ptRecord; # record to add to the output point SoilTypes table
class RVC_RECORDNUM recNumPt; # record number of new record in SoilTypes table
class RVC_ELEMENT ptElement; # class instance needed to set up record attachment
ptElement.Type = "Point";
### Main processing loop
# Loop through the records in the CLASS polygon table and read value from Class field.
# Find the related record in the DESCRIPTN and YIELD tables and read required attribute values.
# Make new record with these field values in the output point soil type table.
# Get list of polygons that the current CLASS record is attached to, make output point at
# the polygon centroid table and attach the soil type record to it.
for i = 1 to classTbl.GetNumRecords()
{
recNumClass.Number = i; # set number in RVC_RECORDNUM for current record
classTbl.Read(recNumClass, classRecord); # read the record from the CLASS table
classRecord.GetValueString("Class", symbol$); # read the string from the Class field (SYMBOL in the other tables)
# polygons in WATER class don't have records in the DESCRIPTN and YIELD tables so
# check that a related record was found before trying to read values.
# get first (in this case only) related record from the DESCRIPTN table
numRelated = descriptnTbl.GetRelatedRecords(classRecord, recNumList);
if (numRelated > 0) {
descriptnTbl.Read(recNumList[1], record); # read the related record from the DESCRIPTN table
record.GetValueString("NAME", name$); # read the string from the NAME field
}
else
name$ = "Waterbody";
# get first (in this case only) related record from the YIELD table
numRelated = yieldTbl.GetRelatedRecords(classRecord, recNumList);
if (numRelated > 0) {
yieldTbl.Read(recNumList[1], record); # read the related record from the YIELD table
wheatnum = record.GetValue("WHEAT"); # read numeric value from the WHEAT field
}
else
wheatnum = 0;
# printf("Class record %d, Class = %s, yield = %.1f\n", i, symbol$, wheatnum);
# printf("HasAttachedElements returned %d\n", polyDB.HasAttachedElements(classRecord) ) ;
#### Make new record in the output point SoilTypes table with these values
ptRecord.AssignTable(soilTypeTbl); # initialize blank record for this table
ptRecord.SetValue("SYMBOL", symbol$); # set field values from current soil attributes
ptRecord.SetValue("SOIL", name$);
ptRecord.SetValue("WHEAT_YLD", wheatnum);
soilTypeTbl.AddRecord(ptRecord, recNumPt); # add record and get the record number returned
printf("New point table record number = %d\n", recNumPt.Number );
# set up an element attachment item for this table and record
class RVC_DBASE_ELEMENT_ATTACHMENTITEM attachmentItem(soilTypeTbl, recNumPt);
printf("Table number from attachmentitem = %d\n", attachmentItem.GetTableNum());
# get list of polygons the current CLASS record is attached to
numAttached = polyDB.GetAttachedElements(classRecord, elemlist);
printf("CLASS record %d, number of attached polygons = %d\n", i, numAttached);
### loop through the list of attached polygons to get centroid location, create point, and attach record
for j = 1 to numAttached
{
# get record number of first record from the POLYSTATS table attached to this polygon
polyDB.GetAttachedRecordNumbers(elemlist[j], polystatsTbl, recNumPolystats, "FirstMatch");
# read the record
polystatsTbl.Read(recNumPolystats[1], record);
# read the coordinates of the polygon centroid from the CentX and CentY fields in the record
pt.x = record.GetValue("CentX");
pt.y = record.GetValue("CentY");
# transform point coordinates to map coordinates
pt = transObjToMap.ConvertPoint2DFwd(pt);
# add new point to output vector at polygon centroid location
VectorAddPoint( VectOut, pt.x, pt.y );
++pointnum; # increment the point element counter
# set the element number for the RVC_ELEMENT class for the new point
# and attach the new record in the SoilTypes table
ptElement.Number = pointnum;
pointDB.AddAttachment(ptElement, attachmentItem);
printf("Created point and attached attributes for polygon %d, %d of %d polygons for this soil type.\n",
elemlist[j].Number, j, numAttached);
}
}
VectorValidate( VectOut );
CloseVector( VectOut );
print("Done.");
# End