More scripts: Database

Syntax Highlighing:

comments, key words, predefined symbols, class members & methods, functions & classes
# 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$;
### 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.
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
polyDB.OpenAsSubobject(VectIn, "Read");
# open the "CLASS" polygon table
class RVC_DBTABLE classTbl;
classTbl.Open(polyDB, descriptor, "Read");
# open the "DESCRIPTN" polygon table
class RVC_DBTABLE descriptnTbl;	 
descriptnTbl.Open(polyDB, descriptor, "Read");
# open the "YIELD" polygon table
class RVC_DBTABLE yieldTbl;
yieldTbl.Open(polyDB, descriptor, "Read");
# open the "POLYSTATS" polygon table
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.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.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.SetDescription("Table created by SML script.");
# set up the "SYMBOL" field parameters
# set up the "SOIL" field parameters
# set up the "WHEAT_YLD" field parameters
fieldinfo[3].SetType("UByte");	# unsigned 1-byte (8-bit) integer, 0 to 255 range
# 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
		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
		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 );
# End