fragtool.sml

  Download

More scripts: Display Toolbar

Syntax Highlighing:

comments, key words, predefined symbols, class members & methods, functions & classes
            
############################################################################
#  Fragtool.sml
#  Created by: Mark Smith
#  Most recent revision: 5-2001
#  This toolscript allows the user to draw a region using a region tool.  It
#  then uses the region to mask the active layer (provided it is an integer-
#  value raster) to extract a raster usable by fragstats.  It writes the
#  output raster to a text file and calls fragstats using a set of default
#  parameters after querying the user for the edge distance value.
#
#  The active layer must be an integer-value, single raster with square cells.
#  Later versions may support more formats.
#
#  This script requires the fragstats executable which is installed in the TNT
#  mips win32 directory and that the temporary folder path specified by mips
#  have folder names no greater than 8 characters long or have spaces in them.
# Variable declarations
class XmForm form, buttonRow;
class PushButtonItem closeButton;
class MdispRegionTool tool;
class Raster targetRaster;
class GRE_LAYER rasterLayer;
string rasterName$, frag$;
class XmDrawingArea da;
class GC gc;
class GRE_GROUP group;
class FILE outFile;
numeric setDefaultWhenClose = false;
# Checks layer to see if it is valid.
func checkLayer() {
	local numeric valid = false;
	# Get name of active layer if it is usable.  If not output an error message.
	if (group.ActiveLayer.Type == "") {
		rasterName$ = "Group has no layers!";
		}
	else {
		if (group.ActiveLayer.Type == "Raster") {
			rasterLayer = group.ActiveLayer;
			DispGetRasterFromLayer(targetRaster, rasterLayer);
			if (targetRaster.$Info.Type == "32-bit floating-point" or targetRaster.$Info.Type == "64-bit floating-point") {
				rasterName$ = "Raster type not supported!";
				}
			else {
				rasterName$ = rasterLayer.Name;
				valid = true;
				}
			}
		else
			rasterName$ = "Not a raster!";
		}
	return valid;
	}
# Callback for drawing area expose.  Draws text.
proc cbRedraw() {
	if (gc == 0) return;
	ActivateGC(gc);
	# Clear the drawing area and redraw text.
	SetColorName("gray75");
	FillRect(0, 0, da.width, da.height);
	SetColorName("black");
	DrawInterfaceText(rasterName$, 0, 12);
	}
# Callback for when the active layer changes.
proc cbLayer() {
	checkLayer();
	cbRedraw();
	}
# Callback for when the active group changes.
proc cbGroup() {
	group = Layout.ActiveGroup;
	WidgetAddCallback(group.LayerSelectedCallback, cbLayer);
	cbLayer();
	}
# Callback for when user clicks the right mouse button on the polygon tool
# (or clicks apply).
proc cbToolApply(class RegionTool tool) {
	# If the selected layer is not valid, don't do anything.
	if (checkLayer()) {
		# Set local variables
		local region MyRgn;
		local class StatusHandle status;
		local class StatusContext context;
		local numeric lins, cols, csize, edist, value;
		string type$, tempFile$, fragout$, realout$;
		# Create a status bar so user knows the script is doing something.
		status = StatusDialogCreate(form);
		context = StatusContextCreate(status);
		StatusSetMessage(context, "Running fragstats...");
		# Get region.
		MyRgn = tool.Region;
		MyRgn = RegionTrans(MyRgn, ViewGetTransViewToScreen(View, 1));
		MyRgn = RegionTrans(MyRgn, ViewGetTransLayerToView(View, rasterLayer, 1));
		lins = NumLins(targetRaster);
		cols = NumCols(targetRaster);
		tempFile$ = CreateTempFileName();
		realout$ = "";
		fragout$ = GetToken(GetOutputFileName(_context.ScriptDir, "Where would you like the results?", ""), ".", 0);
		local numeric i;
		local string temp$;
		for i = 1 to NumberTokens(fragout$, "\") {
			temp$ = GetToken(fragout$, "\", i);
			if (strlen(temp$)>8 or NumberTokens(temp$, " ")>1) {
				realout$ = fragout$;
				fragout$ = FileNameGetPath(tempFile$)+"\"+FileNameGetName(tempFile$);
				break;
				}
			}
		if (FileNameGetName(fragout$)=="")
			goto cleanup;
		csize = (LinScale(targetRaster) + ColScale(targetRaster)) / 2;
		edist = PopupNum("Enter the edge distance in meters:");
		# Write to text file
		outFile = fopen(tempFile$);
		# Apply the region for fragstats' use
		IgnoreNull(targetRaster);
		value = 32071;			# Fragstats won't use anything larger than this value
		local numeric row, column;
		for row = 1 to lins step 1 {
			for column = 1 to cols step 1 {
				if (PointInRegion(column, row, MyRgn)) {
					fprintf(outFile, "%d ", targetRaster[row, column]);
					}
				else
					fprintf(outFile, "%d ", -value);
				}
			if (row != lins)
				fprintf(outFile, "\n");
			}
		# Close output file
		fclose(outFile);
		# Run fragstats
		run(sprintf("%s %s %s %d %d 2 %d %d %d $ $ $ $ $ y y y y y", frag$, tempFile$, fragout$, csize, edist, lins, cols, value), 1);
		if (realout$ != "") {
			CopyFile(fragout$+".cla", realout$+".cla");
			DeleteFile(fragout$+".cla");
			CopyFile(fragout$+".ful", realout$+".ful");
			DeleteFile(fragout$+".ful");
			CopyFile(fragout$+".lnd", realout$+".lnd");
			DeleteFile(fragout$+".lnd");
			CopyFile(fragout$+".pat", realout$+".pat");
			DeleteFile(fragout$+".pat");
			}
	cleanup:
		# Cleanup
		#DeleteFile(Rout.$Info.Filename);
		DeleteFile(tempFile$);
		# Destroy the status bar
		StatusContextDestroy(context);
		StatusDialogDestroy(status);
		}
	else PopupMessage(rasterName$);
	}
# Called when the close button is pressed.  Closes the dialogs.
proc cbClose() {
	tool.Managed = 0;
	DialogClose(form);
	if (setDefaultWhenClose) {
		setDefaultWhenClose = false;
		View.SetDefaultTool();
		}
	}
# Called the first time the tool is activated.
# If the tool implements a dialog it should be created (but not displayed) here.
func OnInitialize () {
	if (Layout!=null) {
		WidgetAddCallback(Layout.GroupSelectedCallback, cbGroup);
		group = Layout.ActiveGroup;
		}
	else
		group = Group;
	WidgetAddCallback(group.LayerSelectedCallback, cbLayer);
	# Set up tool dialog.
	form = CreateFormDialog("Fragstat");
	form.marginHeight = 2;
	form.marginWidth = 2;
	WidgetAddCallback(form.Shell.PopdownCallback, cbClose);
	# Drawing area for displaying text.
	da = CreateDrawingArea(form, 15, 400);
	da.topWidget = form;
	da.leftWidget = form;
	da.rightWidget = form;
	WidgetAddCallback(da.ExposeCallback, cbRedraw);
	# Separator between drawing area and close button.
	class XmSeparator line;
	line = CreateHorizontalSeparator(form);
	line.topWidget = da;
	line.leftWidget = form;
	line.rightWidget = form;
	line.topOffset = 2;
	# Closes the dialog.
	closeButton = CreatePushButtonItem("Close", cbClose);
	# Row of buttons.
	buttonRow = CreateButtonRow(form, closeButton);
	buttonRow.topWidget = line;
	buttonRow.leftWidget = form;
	buttonRow.rightWidget = form;
	buttonRow.bottomWidget = form;
	# Add create polygon tool.
	tool = ViewCreatePolygonTool(View);
	ToolAddCallback(tool.ActivateCallback, cbToolApply);
	frag$ = GetInputFileName("c:/tnt/win32/fragstat.exe", "Please locate the fragstat executable.", "exe");
	}  # end of OnInitialize 
 
# Called when tool is to be destroyed, will not be called if tool was never activated.
func OnDestroy () {
	tool.Managed = 0;
	DestroyGC(gc);
	DestroyWidget(form);
	}  # end of OnDestroy 
 
# Called when tool is activated.
func OnActivate () {
	checkLayer();
	tool.Managed = 1;
	tool.HasPosition = 0;
	DialogOpen(form);
	if (gc == 0)
		gc = CreateGCForDrawingArea(da);
	cbRedraw();
	setDefaultWhenClose = true;
	}  # end of OnActivate 
 
# Called when tool is deactivated (usually when switching to another tool).
func OnDeactivate () {
	setDefaultWhenClose = false;
	cbClose();
	}  # end of OnDeactivate