ProvisionSection.sml

  Download

More scripts: Raster

Syntax Highlighing:

comments, key words, predefined symbols, class members & methods, functions & classes
            
# ProvisionSection_test.sml
# Image provisioning script for extracting Nebraska orthoimage for Township, Range, and Section.
# Version 7 October 2013 for TNTmips 2014
#		- omits setting printable width/height of section layout;
#		 these class members are now read-only. 
# Version 6 June 2011
#		- fixes error trying to parse RVC path to set caption text.
# Version 5 June 2009 incorporating:
#		- User chooses T-R-Dir-Section, year of the orthoimagery, provides a title, and chooses whether
#		- to overlay the section boundary on the image.
# 	- Output is a zipped PDF file with otional section image / overlay, title above the image, and
#		- a caption with the section location and year of imagery.
#		- Script reprojects section to custom NED83 / Orthographic CRS centered on section
#		  to provide a section image with section boundary as parallel to extents as possible.
#		- Use Finish method to close the PDF file to allow it to be zipped.
#		- taskID appended to readme filename
#		- error notification procedure added to e-mail staff on specific errors  5 June 09 
#############################################################
# uncomment the following preprocessor command to run in test mode
# with hard-coded job parameters outside of the Job Control environment
$define TEST
############   Variables to be provided by the job file   #################
#string taskID$;
#string userEmail$;
string rvcPath$;		# string with filepath to source RVC file
string rvcObject$;	# string with name of RVC raster (not the object path)
string outFormat$;	# output file format
string limit$;				# size limit: possible values "tntlite" or "max"
numeric lossyComp;		# compression ratio for JP2 lossy compression, 0 for lossless
numeric boundary;		# flag indicating whether to draw section boundary
string township$;	# township number
string range$;			# range number
string direction$;	# range direction, E or W
string section$;		# section number
string title$;				# title for the image
################################################################
################  Job parameters for test mode  ###################
$ifdef TEST
#		string rvcPath$ =  _context.ScriptDir + "/provision/ProvisionNE.rvc";
#		string taskID$ = "50020";
#		string rvcObject$ = "NE 2006 NC UTM14 1m 15to1";
#		string outFormat$ = "PDF";
#		string userEmail$ = "[email protected]";
		string limit$ = "max";
		numeric lossyComp = 15;
		numeric boundary = 1;
		string township$ = "32";
		string range$ = "47";
		string direction$	= "W";
		string section$ = "21";
		string title$ = "Kimball Farm";
$endif
##############################################################
############  Output format constrained to PDF  #####################
string outFormat$ = "PDF";
#############  VARIABLES FOR AUTOMATED TESTING  ####################
# read from control file
string correctfilepath$;						# path to file with correct output
string correctobjectpath$;					# object path to correct object
string vecFilename$;
#--------------------------------------
#string outfilepath$ = CreateTempFileName();		# temporary output file for non-rvc target
string rvcfilepath$ = CreateTempFileName();		# temporary project file for rvc target
#class FILEPATH outFilepath = outfilepath$;
class FILEPATH correctfile = correctfilepath$; 		# path to file with correct output
class RVC_OBJITEM outobjitem;
CreateProjectFile(rvcfilepath$, "Provision Section Test");
outobjitem.SetFilePath(rvcfilepath$);
outobjitem.SetObjectPath(correctobjectpath$);
class RVC_DESCRIPTOR desc;
desc.SetName(correctobjectpath$);
desc.SetDescription("Provision Section Test");
outobjitem.CreateNew(desc, "RASTER");
class RVC_RASTER RDest;
##################   Other variables   ###################
class RVC_RASTER RastIn;		# the source image raster
class REGION2D exRegion;		# region to use for extraction
class DATETIME currentDT;		# the current local date/time
class EMAIL_MESSAGE email;
class STRING logfileName$;
class STRING readmeFilename$;
class FILE logfile;
class FILE readme;
class STRING outpath$;			# path string for output www jobs directory
class STRING outDirPath$;		# path string for output directory created in www jobs directory
class FILEPATH outFilepath;	# filepath for output directory
class STRING outputFileExtension$;
numeric err;		# error value from defined functions
string error$;		# string with error text
class STRING tr$;				# Township-range identifier as direction$+township$+range$
class STRING year$;		# year of the selected orthoimage mosaic, for caption
class STRING caption$;		# text for caption below the section image
class ZIPFILE zip;
class FILEPATH zipFilepath;
string start$,  finish$;
class TIMER timer;
######  Variables for resampling to new cell size to meet image size limit #############
numeric numLins, numCols;		# number of lines and columns in extraction area
numeric totalCells;						# number of cells in extracted image
numeric limitCells;							# maximum allowed number of cells in output
class POINT2D rastScale;			# source raster x and y scales computed from georeference
numeric rescale;								# scale factor for rescaling line and column scales for output
string inCRS$;											# EPSG code for CRS of source image
string outCRS$;										# EPSG code for output, read from section table
class SR_COORDREFSYS inCRS;		# CRS of source image
class SR_COORDREFSYS outCRS;	# output CRS
# error notification procedure
proc notifyError(string err$) {
#	string php$ = "php c:/wamp/www/error.php " +  taskID$;
#	fprint(logfile, err$);
#	fclose(logfile);
#	fprint(readme, err$);
#	fclose(readme); 
#	email.SetSubject(sprintf("Error with provisioning job %s", taskID$) );
#	email.SetBody(err$);
#	email.SetRecipient("[email protected]");
#	email.SendMail();
#	email.SetRecipient("[email protected]");
#	email.SendMail();
#	ExecuteProcess(php$);
#	Exit();
	}
# error checking procedure
proc ReportError(numeric linenum, numeric err) {
	print("FAILED -line: %d, error: %d\n", linenum - 1, err);
	Exit();  
	}
############################################################
########################  Program  ###########################
clear();
#timer.Running = 1;
### set up to run php scripts to write info to MySQL database
#start$ = "php c:/wamp/www/start.php " +  taskID$;
#finish$ = "php c:/wamp/www/finish.php " +  taskID$;
#ExecuteProcess(start$);
########################  Set up Log File  ######################
# open log file to append status information
#logfileName$ = _context.ScriptDir + "/Provisioning.log";
#logfile = fopen(logfileName$, "a");
#print("Logfile opened.");
#currentDT.SetCurrent();
#fprintf(logfile, "\nJob initiated %s Central Standard Time\n", currentDT);
#$ifdef TEST
		# print job info to console
#		printf("TaskID: %s\n", taskID$);
#		printf("User Email: %s\n", userEmail$);
#		printf("RVCpath: %s\n", rvcPath$);
#		printf("RVCobject: %s\n", rvcObject$);
#		printf("Selected output format: %s\n", outFormat$);
#		printf("Limit = %s\n", limit$);
#$endif
# print job info to log file
#fprintf(logfile, "TaskID: %s\n", taskID$);
#fprintf(logfile, "User Email: %s\n", userEmail$);
#fprintf(logfile, "RVCpath: %s\n", rvcPath$);
#fprintf(logfile, "RVCobject: %s\n", rvcObject$);
#fprintf(logfile, "Selected output format: %s\n", outFormat$);
#fprintf(logfile, "Limit = %s\n", limit$);
#####################  Other  File Handling  ######################
# set up output directory
#$ ifdef TEST
#			outpath$ = _context.ScriptDir + "/";
#$ else
#			outpath$ = "C:/wamp/www/jobs/"; 
#$ endif
#outDirPath$ = outpath$ + taskID$;		# new directory to be created for this job
#CreateDir(outDirPath$);						# create new directory
#outFilepath = outDirPath$ + "/" + taskID$;						# filepath for output file (minus extension)
# set filepath for zipfile in output directory
#if (outFormat$ == "KMZ") then
#	zipFilepath = outDirPath$ + "/" + taskID$ + ".kmz";
#else
#	zipFilepath = outDirPath$ + "/" + taskID$ + ".zip";
#readmeFilename$ = outDirPath$ + "/readme" + taskID$ + ".txt";
#$ifdef TEST											# delete previously existing zip file with same path/name
#	if ( fexists(zipFilepath) ) then
#		DeleteFile(zipFilepath);
#$endif
# open readme file
#readme = fopen(readmeFilename$, "a");
#fprintf(logfile, "New directory path: %s\n", outDirPath$);
#fprintf(logfile, "outFilepath = %s\n", outFilepath.GetPath() );
#fprintf(logfile, "Zip file path = %s\n", zipFilepath.GetPath() );
#fprintf(logfile, "readmeFilename$ = %s\n", readmeFilename$);
#$ifdef TEST
#		printf("New directory path: %s\n", outDirPath$);
#		printf("Zip file path = %s\n", zipFilepath.GetPath() + "/" +  zipFilepath.GetName() );
#		printf("readmeFilename$ = %s\n", readmeFilename$);
#$endif
# set up e-mail source
#email.SetSourceAddress("[email protected]");
#email.SetSourceName("GeoProvisioning at MicroImages.com");
#######################################################################
#####################  Make S-T-R caption for image  ########################
# year$ = GetToken(rvcPath$, "/\\", 2);
caption$ = sprintf("Township %s, Range %s %s, Section %s", township$, range$, direction$, section$); 
# caption$ = sprintf("%s\nNebraska %s", caption$, year$);
caption$ = sprintf("%s\nNebraska SML test", caption$);
#fprintf(logfile, "Caption: %s \n\n", caption$);
#######################################################################
######################  Modify strings for section search  ####################
if (strlen(township$) == 1) then township$ = "0" + township$;
if(strlen(range$) == 1) then range$ = "0" + range$; 
if(strlen(section$) == 1) then section$ = "0" + section$;
tr$ = direction$ + township$ + range$;		# make township-range string for TR field check
#fprintf(logfile, "TR search string: %s\n", tr$);
#########################################################################
###################  Find section polygon in section vector  ####################
class RVC_VECTOR sections;				# vector object with Nebraska sections in NAD83 / UTM zone 14N
#class STRING vecFilename$ = _context.ScriptDir + "/provision/NE_TRS_UTM14.rvc";
class STRING vecObjname$ = "NE_Sections_UTM14";
numeric numRecords;			# number of records
array numeric townshipList[1];		# array to hold list of records matching selected township-range
numeric i;					# counter to loop through list of records matching selected township-range
numeric recNum;		# current record number in the list
numeric numPolys;				# number of polygons attached to the matching section record (should be 1)
array numeric polyArray[1];		# array to hold the element numbers of polygons attached to the section record
numeric polyNum;				# the element number of the matching polygon
# open the vector object containing the sections
OpenVector(sections, vecFilename$, vecObjname$);
class GEOREF vectGeoref;
vectGeoref = GetLastUsedGeorefObject(sections);
#####  Find all records in section_poly table matching the selected township-range
numRecords = TableKeyFieldLookupList(sections.Poly.section_poly, "TR", tr$, townshipList, "Equals");
####  Search through the returned set of records for the one matching the requested section
for i = 1 to numRecords
	{
	recNum = townshipList[i];
	if (sections.Poly.section_poly[@recNum].SECTION_$ == section$)
		{ 
		numPolys = TableGetRecordElementList(sections.Poly.section_poly, recNum, polyArray);
		polyNum = polyArray[1];
		}
	}
# read latitude and longitude of center point of section from the table  
numeric centerLong = sections.Poly.section_poly[polyNum].LONG;
numeric centerLat = sections.Poly.section_poly[polyNum].LAT;
#fprintf(logfile, "Township-Range = %s, Section = %s\n", tr$, section$);
#fprintf(logfile, "%d records match the selected township-range\n", numRecords);
#fprintf(logfile, "%d polygons are attached to the section record\n", numPolys);
#fprintf(logfile, "The output CRS ID is %s\n", outCRS$); 
#$ifdef TEST
#		printf("Township-Range = %s, Section = %s\n", tr$, section$);
#		printf("%d records match the selected township-range\n", numRecords);
#		printf("%d polygons are attached to the section record\n", numPolys);
#		printf("Section center coordinates Lat = %.8f, Long = %.8f\n", centerLat, centerLong); 
#$endif
##########################################################################
##############  Create region from selected section polygon  #####################
class REGION2D sectionRegion;
sectionRegion = ConvertVectorPolyToRegion(sections, polyNum, vectGeoref); 
sections.Close();
#fprint(logfile, "Extents of area to extract in the source CRS: ");
#fprintf(logfile, "min x: %.6f, min y: %.6f, max x: %.6f, max y: %.6f\n", sectionRegion.Extents.x1, sectionRegion.Extents.y1, sectionRegion.Extents.x2, sectionRegion.Extents.y2);
#$ifdef TEST
#		print("Extents of area to extract in the source CRS: ");
#		printf("min x: %.6f, min y: %.6f, max x: %.6f, max y: %.6f\n", sectionRegion.Extents.x1, sectionRegion.Extents.y1, sectionRegion.Extents.x2, sectionRegion.Extents.y2);
#$endif
# get center point of section in map coordinates
class POINT2D centerPt;
centerPt = sectionRegion.GetCentroid();
####################################################################
#######################  Source Image  #################################
# open the input raster to get an RVC_OBJITEM to use to set up a pipeline source
OpenRaster(RastIn, rvcPath$, rvcObject$);
class RVC_OBJITEM sourceObjItem;
sourceObjItem = RastIn.GetObjItem();
RastIn.Close();
if (!sourceObjItem.IsExisting() ) {
	error$ = "Source raster cannot be found.";
	print("FAILED - source raster cannot be found.");
	Exit();
	}
##########################################################
##########  set up pipeline source for source image  #############
class IMAGE_PIPELINE_SOURCE_RVC sourceRVC(sourceObjItem);
err = sourceRVC.Initialize();
if (err < 0) 	{ 
	ReportError(_context.CurrentLineNum, err);
#	notifyError(error$);
	}
# get pipeline georeference from the source image
class IMAGE_PIPELINE_GEOREFERENCE georefSource;		# georeference from source
georefSource = sourceRVC.GetGeoreference();
inCRS = georefSource.GetCRS();
inCRS$ = "EPSG:" + inCRS.GetID("EPSG");
# get coordinate transformation from source image to its defined CRS
class TRANS2D_MAPGEN transImgToCRS = georefSource.GetTransGen();
# compute center point of extraction area in image coordinates
class POINT2D centerPtImg;
centerPtImg = transImgToCRS.ConvertPoint2DInv(centerPt);
# compute cell sizes (scales) at center of extraction area of source image from its georeference
georefSource.ComputeScale(centerPtImg, rastScale, 0);
#fprint(logfile, "\nSource raster info:");
#fprintf(logfile, "RastIn object name: %s\n\n", RastIn.$Info.Name);
#fprintf(logfile, "Raster cols: %d, lines: %d\n", sourceRVC.GetTotalColumns(), sourceRVC.GetTotalRows() );
#fprintf(logfile, "Source CRS: %s, %s\n", inCRS$, inCRS.Name);
#fprintf(logfile, "Native cell size of source image: x = %.3f, y = %.3f\n", rastScale.x, rastScale.y);
#fprint(readme, "Details of your provisioning order:");
#fprintf(readme, "You requested a %s image for Section %s, Township %s N, Range %s %s", year$, section$, township$, range$, direction$);
#fprintf(readme, "\nCoordinate Reference System of the source image: %s\n", inCRS.Name);
#fprintf(readme, "Native cell size of source image: x = %.3f, y = %.3f\n", rastScale.x, rastScale.y);
#$ifdef TEST
#		print("\nSource raster info:");
#		printf("RastIn object name: %s\n\n", RastIn.$Info.Name);
#		printf("Raster cols: %d, lines: %d\n", sourceRVC.GetTotalColumns(), sourceRVC.GetTotalRows() );
#		printf("Source CRS: %s, %s\n", inCRS$, inCRS.Name);
#		printf("Native cell size of source image: x = %.3f, y = %.3f\n", rastScale.x, rastScale.y);
#$endif
##############################################################
###############  check extraction area  ###########################
# get extents of the image source as a region
class REGION2D sourceRegion;
err = sourceRVC.ComputeGeoreferenceRegion(sourceRegion);
if (err < 0)  {
	ReportError(_context.CurrentLineNum, err);
	#notifyError(error$);
	}
#$ifdef TEST 
#		print("Source raster extents:");
#		printf("Min x: %.4f, Min y: %.4f, Max x: %.4f, Max y: %.4f\n",
#			sourceRegion.Extents.x1, sourceRegion.Extents.y1, sourceRegion.Extents.x2, sourceRegion.Extents.y2);
#$endif
# check that extraction region is contained within the source image extents region
if (sourceRegion.TestRegion(exRegion, "FullInside") )
	{
#	fprint(logfile, "Source image contains extraction extents.");
#	fprint(readme, "The source image contains the provided extraction extents.");
#	$ifdef TEST
#			print("Source image contains extraction extents.");
#	$endif
	}
else
	{
#	error$ = "Extraction areas is outside the extents of the source image. No extracted image was created.";
#	fprint(logfile, error$); 
#	fprint(readme, "The desired extraction area is outside the extents of the source image.");
#	fprint(readme, "No extracted image could be created.");
	$ifdef TEST
			print("FAILED - Extraction areas is outside the extents of the source image. No extracted image was created.");
			Exit();
	$endif
#	notifyError(error$);
#	return;
	}
##########################################################################
### Set up custom output CRS centered on the section  so the section outline 
### appears upright in the PDF file.
class SR_DATUM datum;
datum = inCRS.Datum;		# use NAD83 datum from input raster
class SR_COORDSYS outCoordSys;
outCoordSys.Assign("1200");		# assign using MicroImages numeric ID for Projected E and N, meters
# set up orthographic projection centered on the center of the section
#class SR_COORDOPMETHOD method("Orthographic");
class SR_COORDOPMETHOD method;
method.Assign("Orthographic");
class SR_COORDOPDEF projection;
projection.Method = method;
projection.SetParmValueNum("LatitudeOfNaturalOrigin", centerLat);
projection.SetParmValueNum("LongitudeOfNaturalOrigin", centerLong);
projection.SetParmValueNum("FalseEasting", 0);
projection.SetParmValueNum("FalseNorthing", 0);
#caption$ = sprintf("%s\nNAD83 / %s", caption$, "Orthographic");
outCRS.Create(outCoordSys, datum, projection);
sectionRegion.ConvertTo(outCRS);
#$ifdef TEST
#			printf("The section extract will be reprojected to %s\n", outCRS.Name);
#$endif
##########################################################################
##################   Compute buffered extents of section  ######################
class RECT exRect;		# extents of the section image in output map coordinates
exRect = sectionRegion.Extents;
exRect.Expand(100, 100);
###########################################################################
##################  Compute output image dimensions  #########################
numLins = abs(round( (exRect.y2 - exRect.y1) / rastScale.y) );
numCols = round( (exRect.x2 - exRect.x1) / rastScale.x);
class IMAGE_PIPELINE_DIMENSIONS dimensions;			# set output image dimensions for pipeline
dimensions.SetTotalDimensions(numCols, numLins);
#fprint(logfile, "Extents of the extraction area in the output coordinate reference system:");
#fprintf(logfile, "Min x: %.4f, Min y: %.4f, Max x: %.4f, Max y: %.4f\n", exRect.x1, exRect.y1, exRect.x2, exRect.y2);
#fprintf(logfile, "Output image dimensions at native cell size: %d lines, %d columns\n", numLins, numCols); 
#$ifdef TEST
#		print("Extents of the extraction area in the output coordinate reference system:"); 
#		printf("Min x: %.4f, Min y: %.4f, Max x: %.4f, Max y: %.4f\n", exRect.x1, exRect.y1, exRect.x2, exRect.y2);
#		printf("Output image dimensions at native cell size: %d lines, %d columns\n", numLins, numCols);
#$endif
#################################################################
##############   Set up affine georeference for target image  ############# 
class TRANS2D_AFFINE transAffine;
transAffine.ApplyScale(rastScale.x, rastScale.y);
transAffine.ApplyOffset(exRect.x1, exRect.y2);
#fprint(logfile, "Affine transformation parameters:");
#fprintf(logfile, "Forward: x scale = %.6f, y scale = %.6f\n", transAffine.GetForwardScaleX(), transAffine.GetForwardScaleY() );
#fprintf(logfile, "Forward shear = %.6f\n", transAffine.GetForwardShear() );
#$ifdef TEST
#		print("Affine transformation parameters:");
#		printf("Forward: x scale = %.6f, y scale = %.6f\n", transAffine.GetForwardScaleX(), transAffine.GetForwardScaleY() );
#		printf("Forward shear = %.6f\n", transAffine.GetForwardShear() );
#$endif
class IMAGE_PIPELINE_GEOREFERENCE targetGeoref;
targetGeoref.SetTransAffine(outCRS, transAffine);
#fclose(logfile);
#logfile = fopen(logfileName$, "a");
###########################################################
#####   set up pipeline filter to resample the image    #######
class IMAGE_PIPELINE_FILTER_RESAMPLE filterResample(sourceRVC, dimensions, targetGeoref, "Nearest");
err = filterResample.Initialize();
if (err < 0)  {
	ReportError(_context.CurrentLineNum, err);
	#notifyError(error$);
	}
#fprintf(logfile, "filterResample initialized, returned %d\n", err);
#fclose(logfile);
#logfile = fopen(logfileName$, "a");
#$ifdef TEST
#		printf("filterResample initialized, returned %d\n", err);
#$endif
############################################################
#####  set up pipeline filter target and process  ##########
class IMAGE_PIPELINE_TARGET target;			# generic pipeline target, to be assigned specific type
switch (outFormat$)
	{
	case "PDF":
		# create temporary Project File for temp raster
		class RVC_OBJECT outRVC;
		outFilepath.SetExtension(".rvc");
		printf("Filepath = %s\n", outFilepath);
	 	outRVC.MakeTempFile(1);		# delete on close 
		class RVC_OBJITEM outFileObjItem;			# ObjItem for the project file to serve as parent
		outFileObjItem = outRVC.GetObjItem();
		# RVC_OBJITEM for the new raster object
		class RVC_OBJITEM outRastObjItem;	# ObjItem for the output raster
		class RVC_DESCRIPTOR descriptor;
		descriptor.SetName("Rendered");
		descriptor.SetDescription("Provisioning result");
		outRastObjItem.CreateNew(outFileObjItem, "RASTER", descriptor);
		class IMAGE_PIPELINE_TARGET_RVC targetRVC(filterResample, 	outRastObjItem);
		target = targetRVC;
		break;
	}
err = target.Initialize();
if (err < 0)  {
	ReportError(_context.CurrentLineNum, err);
	#notifyError(error$);
	}
#fprintf(logfile, "target initialization returned: %d\n", err);
#$ifdef TEST
#		printf("target initialization returned: %d\n", err);
#$endif
err = target.Process();
if (err < 0)  { 
	ReportError(_context.CurrentLineNum, err);
	#notifyError(error$);
	}
#fprintf(logfile, "target process returned: %d\n", err);
#$ifdef TEST
#		printf("target process returned: %d\n", err);
#$endif
#################   Make PDF File from RVC Target  #########################
if (outFormat$ == "PDF")
	{
	# set up a hardcopy layout with group containing the output raster and render to PDF
#	fprint(logfile, "Setting up layout to render to PDF.");
	class PRINTPARMS printparms;		# page size and scale settings for hardcopy layou	t
	numeric inTOm = GetUnitConvDist("in", "m");			# scale factor from inches to meters
	numeric imgSize, printSize;
	# set up 8.5 x 11 in page in portrait orientation (printable area 7.5 x 10 in, aspect ratio 1.333)
	printparms.FullWidth = 8.5; 					# width in inches including margins
	printparms.FullHeight = 11;					# height in inches including margins
	#printparms.PrintableWidth = 7.5;
	#printparms.PrintableHeight = 10;
	# set layout scale from image/page width
	imgSize = numCols * rastScale.x;					# image ground width in meters
	printSize = 7.0 * inTOm;										# allowed printed size in meters 
	printparms.MapScale = imgSize / printSize;
	# set up a virtual hardcopy layout
	class GRE_LAYOUT pdfLayout;
	pdfLayout.Create("pdfLayout", 1);
	pdfLayout.Hardcopy = printparms;
#	$ifdef TEST
#			printf("Layout %s width = %d, height = %d\n", pdfLayout.Name, printparms.FullWidth, printparms.FullHeight);
#			printf("Image ground size = %d, printSize = %.4f\n", imgSize, printSize);
#			printf("Printparms map scale = %d\n", printparms.MapScale);
#			printf("Layout map scale = %d\n", pdfLayout.MapScale);
#	$endif
	# set up group to contain the image
	class GRE_GROUP imgGroup;
	imgGroup = GroupCreate("ImageGroup", pdfLayout);
	imgGroup.AttachVertical("Center", -0.25, "Page", "Center");
#	$ifdef TEST
#			printf("Name of group to render image: %s\n", imgGroup.Name);
#			printf("Name of layout the group belongs to: %s\n", imgGroup.Layout.Name);
#	$endif
	# add output raster to the imgGroup
	class RVC_RASTER outRast;				# handle for the output RVC raster created by the pipeline
	outRastObjItem = targetRVC.GetObjItem();		# get the objItem for the raster from the temporary project file
	err = outRast.Open(outRastObjItem, "Read");
	if (err < 0)  { 
	ReportError(_context.CurrentLineNum, err);
	#notifyError(error$);
	}
	GroupQuickAddRasterVar(imgGroup, outRast);
	###################################################
	#### if user chose to include section boundary overlay in result
	if (boundary)
		{
		# convert section region to vector
		class VECTOR sectionVect;
		CreateTempVector(sectionVect);
		sectionVect = ConvertRegionToVect(sectionRegion);
		# add the section vector overlay to the imgGroup with appropriate styling
		class GRE_GROUP VectorGroup;
		VectorGroup = GroupCreate("VectorGroup", pdfLayout);
		VectorGroup.AttachVertical("Center", -0.25, "Page", "Center");
		class GRE_LAYER_VECTOR vectLayer;
		vectLayer = GroupQuickAddVectorVar(VectorGroup, sectionVect);		# add section vector to group
		# set display parameters for the section outline 
		vectLayer.Poly.Select.Mode = "None";
		vectLayer.Line.Select.Mode = "All";
		class COLOR lineColor("yellow");
		class LINESTYLE lineStyle;
		lineStyle.Color = lineColor;
		lineStyle.UseLayoutScale = 1;
		lineStyle.Width = 0.5;
		vectLayer.Line.StyleMode = "AllSame";
		vectLayer.Line.NormalStyle = lineStyle;
		}
#	$ifdef TEST
#			printf("outRast.Open() returned: %d\n", err);
#			printf("Group name = %s\n", imgGroup.Name);
#			printf("Group angle to north = %.1f\n", imgGroup.AngleToNorth);
#	$endif
	# add Township-Range-Section caption under the image group in the layout
	class TEXTSTYLE captionStyle;			# style parameters for the caption
	captionStyle.Font = "ARIAL.TTF";
	captionStyle.Height = 18;
	captionStyle.LineSpace = 0.25;
	captionStyle.HeightUnits = "Points";
	captionStyle.JustifyCenter = 1;
	class GRE_GROUP captionGroup;
	captionGroup = GroupCreate("Caption Group", pdfLayout);
	captionGroup.AttachHorizontal("Center", 0, "Page", "Center");
	captionGroup.AttachVertical("Top", 0.2, "Group", "Bottom", imgGroup);
	class GRE_LAYER_TEXT captionLayer(captionGroup, "None", "After"); 
	captionLayer.Style = captionStyle;
	captionLayer.Text = caption$;
#	fprintf(logfile, "Caption = %s\n\n", caption$);
	# add user-defined title above the image group in the layout
	class TEXTSTYLE titleStyle;
	titleStyle.Font = "ARIALBD.TTF";
	titleStyle.Height = 24;
	titleStyle.LineSpace = 30;
	titleStyle.HeightUnits = "Points";
	titleStyle.JustifyCenter = 1;
	class GRE_GROUP titleGroup;
	titleGroup = GroupCreate("Title Group", pdfLayout);
	titleGroup.AttachHorizontal("Center", 0, "Page", "Center");
	titleGroup.AttachVertical("Bottom", 0.25, "Group", "Top", imgGroup);
	class GRE_LAYER_TEXT titleLayer(titleGroup, "None", "After");
	titleLayer.Style = titleStyle;
	titleLayer.Text = title$;
#	fprintf(logfile, "Caption = %s\n\n", caption$);
  ##################################
	# render layout to raster in temporary project file
	pdfLayout.RenderToRaster(rvcfilepath$, correctobjectpath$, 1, 1);
	# compare test output
	class RVC_OBJITEM targetobjitem;
	targetobjitem.SetFilePath(correctfilepath$);
	targetobjitem.SetObjectPath(correctobjectpath$);
	if (!targetobjitem.IsExisting()) {#no known good exists
		print("FAILED - No correct image exists for ", outFormat$);
		CopyObject(rvcfilepath$, 1, correctfilepath$);
		}
	OpenRaster(RDest, rvcfilepath$, correctobjectpath$);
	# set up PDF file
#	class PDF pdf;
#	pdf.SetLayout(pdfLayout);
#	pdf.SetResolution(300);
#	outFilepath.SetExtension(".pdf");
#	pdf.SetPath(outFilepath);
#	pdf.Write();
#	pdf.Finish();
	} # end if PDF
##############################  Make ZIP File  ##########################
#fclose(readme);
# Add output image file and delete raw file
#class STRING imageName$ = outFilepath.GetName();
#zip.AddFile(zipFilepath, outFilepath,  imageName$);
#DeleteFile(outFilepath);
# Add readme file
#class Filepath readmeFilepath(readmeFilename$);
#fprintf(logfile, "readmeFilepath = %s + %s\n", readmeFilepath.GetPath(),  readmeFilepath.GetName() );
#zip.AddFile(zipFilepath, readmeFilepath, readmeFilepath.GetName() );
#DeleteFile(readmeFilename$);
######################################################################
#currentDT.SetCurrent();
#$ifdef TEST
#		printf("Job completed %s Central Standard Time\n\n", currentDT);
#$endif
#fprintf(logfile, "Job completed %s Central Standard Time\n", currentDT);
#fprintf(logfile, "##########################################################\n\n");
#fclose(logfile);
#################################################################
#########  SEND EMAIL NOTIFICATION  ############################
#class STRING mailFilename$;
#class STRING emailbody1$, emailbody2$, emailbody3$;
#class STRING emailbody$;
#email.SetSubject(sprintf("Data Provisioning for Job %s Complete", taskID$) );
#mailFilename$ = _context.ScriptDir + "/" + "emailbody1.txt";
#emailbody1$ = TextFileReadFull(mailFilename$);
#emailbody2$ = sprintf("Please download your sample geodata file now from http://www.geoprovisioning.com/jobs/%s/%s%s\n\n", taskID$, taskID$, ".zip");
#mailFilename$ = _context.ScriptDir + "/" + "emailbody3.txt";
#emailbody3$ = TextFileReadFull(mailFilename$);
#emailbody$ = sprintf("%s%s%s", emailbody1$, emailbody2$, emailbody3$);
#email.SetBody(emailbody$);
#email.SetRecipient(userEmail$);
#email.SendMail();
#ExecuteProcess(finish$);
print("Process Completed");