home products news downloads documentation support gallery online maps resellers search
TNTmips Downloads Menu

HOME

CONTACT US

CURRENT RELEASE
  TNT 2013

DEVELOPMENT VERSION
  TNT 2014

TNTmips Pro
PRIOR RELEASES
  TNT 2012

FREE SOFTWARE
  TNTmips Free
  TNTatlas
  TNTsdk

MORE DOWNLOADS
  HASP Key Driver
  Screen Recorder
  TNT Language Kits
  Sample Geodata
  TNT Scripts

DOCUMENTATION
  TNTmips Tutorials
  Tutorial Datasets
  Technical Guides
  Scripts
  Quick Guides

MORE INFO
  Download FAQs
  FTP
  Download Managers
  Find Reseller

SITE MAP


Regstatp.sml

See other examples of Tool and Macro scripts ...


# REGSTATp.SML - Allows user to select an area of a non-composite raster
# by selecting and deselecting polygons from a vector layer over the top of it.
# The script then outputs the number of cells, number of non-null cells,
# minimum, maximum, mean, standard deviation, area, perimeter, centroid,
# and surface area over that region. The user may choose any distance or
# area units for the output to be displayed in. 
#
# Requires TNTmips version 7.0
# Updated 29 April 2005


# The following symbols are predefined
#    class VIEW View            {use to access the view the tool script is attached to}
#    class GROUP Group          {use to access the group being viewed if the script is run from a group view}

# Variable declarations
class XmForm form, buttonRow, plusMinus;
class XmSeparator line1, line2;
class GRE_LAYER_VECTOR vectorLayer;
class GRE_LAYER rasterLayer;
class Vector targetVector;
class Raster targetRaster;
class XmDrawingArea da;
class GC gc;
class PointTool pointTool;
string vectorName$, rasterName$, regionMode$;
class PushButtonItem saveButton, closeButton;
class XmPushButton clearicon;
class ToggleButtonItem plusicon,  minusicon;
class XmOptionMenu distMenu, areaMenu;
class REGION2D reg;
numeric min, max, mean, stdDev, count, cells, sum, sumsqr, surface, area, perimeter;
class POINT2D centroid;
numeric setDefaultWhenClose = false;
numeric distScale, areaScale, numPolys;
array numeric polyarray[1000];
class GRE_GROUP group;

# Checks layer to see if it is valid.
func checkLayer() {
	local numeric valid = false;

	# Get names layers if usable.  If not output error messages.
	if (group.ActiveLayer.TypeID == "") {
		rasterName$ = "Group has no layers!";
		}
	else {
		if (group.LastLayer.TypeID == "Vector") {
			vectorLayer = group.LastLayer;
			DispGetVectorFromLayer(targetVector, vectorLayer);
			if (targetVector.$Info.NumPolys > 0) {
				vectorName$ = vectorLayer.Name;
				valid = true;
				}
			else vectorName$ = "No polygons!";
			}
		else vectorName$ = "Not a vector!";
		if (group.FirstLayer.TypeID == "Raster") {
			rasterLayer = group.FirstLayer;
			DispGetRasterFromLayer(targetRaster, rasterLayer);
			if (targetRaster.$Info.Type != "binary" and
				targetRaster.$Info.Type != "4-bit unsigned" and
				targetRaster.$Info.Type != "8-bit signed" and
				targetRaster.$Info.Type != "8-bit unsigned" and
				targetRaster.$Info.Type != "16-bit signed" and
				targetRaster.$Info.Type != "16-bit unsigned" and
				targetRaster.$Info.Type != "32-bit signed" and
				targetRaster.$Info.Type != "32-bit unsigned" and
				targetRaster.$Info.Type != "32-bit floating-point" and
				targetRaster.$Info.Type != "64-bit signed" and
				targetRaster.$Info.Type != "64-bit unsigned" and
				targetRaster.$Info.Type != "64-bit floating-point") {
				rasterName$ = "Type not supported!";
				valid = false;
				}
			else
				rasterName$ = rasterLayer.Name;
			}
		else {
			rasterName$ = "Not a raster!";
			valid = false;
			}
		}
	return valid;
	}

# Callback for drawing area expose.  Draws text.
proc cbRedraw() {
	local numeric larea, lperimeter, lsurface;

	# Scale the values to specified units.
	larea = areaScale * area;
	lperimeter = distScale * perimeter;
	lsurface = areaScale * surface;
	if (gc == 0) return;
	ActivateGC(gc);

	# Clear the drawing area and redraw text.
	SetColorName("gray75");
	FillRect(0, 0, da.width, da.height);
	SetColorName("black");
	if (cells > 0) {
		DrawInterfaceText(sprintf("Vector: %s\nRaster: %s\nCells: %d\nNull Cells: %d\nMinimum: %.2f\nMaximum: %.2f\nMean: %.2f\nStandard Deviation: %.2f\nArea: %.2f\nPerimeter: %.2f\nCentroid: %.2f, %.2f\nSurface Area: %.2f",vectorName$, rasterName$, count, cells - count, min, max, mean, stdDev, larea, lperimeter, centroid.x, centroid.y, lsurface), 0, 10);
		}
	else DrawInterfaceText(sprintf("Vector: %s\nRaster: %s\nCells:\nNull Cells:\nMinimum:\nMaximum:\nMean:\nStandard Deviation:\nArea:\nPerimeter:\nCentroid:\nSurface Area:",vectorName$, rasterName$), 0, 10);
	}

# 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 pointTool tool) {
	# If the selected layer is not valid, don't do anything.
	if (checkLayer()) {
		# Set local variables
		local numeric sum, sumsqr, xscale, yscale, zscale;
		local numeric current, right, down, downright, elemNum;
		local class POINT2D point;
		local class StatusHandle status;
		local class StatusContext context;
		cells = 0; min = 0; max = 0; mean = 0; stdDev = 0; sum = 0; sumsqr = 0; count = 0; surface = 0; area = 0; perimeter = 0;
		centroid.x = 0; centroid.y = 0; current = 0; right = 0; down = 0; downright = 0;
		xscale = ColScale(targetRaster);
		yscale = LinScale(targetRaster);
		zscale = group.FirstLayer.zscale;

		# Check point.
		point.x = tool.Point.x;
		point.y = tool.Point.y;

		point = TransPoint2D(point, ViewGetTransViewToScreen(View, 1));
		point = TransPoint2D(point, ViewGetTransMapToView(View, vectorLayer.Projection, 1));

		numeric elementNum = FindClosestPoly(targetVector, point.x, point.y, GetLastUsedGeorefObject(targetVector));

		if (elementNum > 0) {
			if (regionMode$ == "plus") {
				# Add to polygon list.
				numPolys += 1;
				polyarray[numPolys] = elementNum;
				vectorLayer.Poly.HighlightSingle(elementNum, "Add");
				}
			else {
				if (numPolys > 1) {
					# Remove from polygon list.
					local numeric i;
					for i = 1 to numPolys
						if (polyarray[i] == elementNum) {
							polyarray[i] = polyarray[numPolys];
							numPolys -= 1;
							vectorLayer.Poly.HighlightSingle(elementNum, "Subtract");
							break;
							}
					}
				else if (numPolys == 1 and polyarray[1] == elementNum) {
					vectorLayer.Poly.HighlightSingle(elementNum, "Subtract");
					numPolys = 0;
					}
				}

			# Get region and transform it to the appropriate coordinate system.
			if (numPolys > 0) {
				reg = ConvertVectorPolysToRegion(targetVector, GetLastUsedGeorefObject(targetVector), polyarray, numPolys);
				}
			else ClearRegion(reg);

			# Create a status bar so user knows the script is doing something.
			status = StatusDialogCreate(form);
			context = StatusContextCreate(status);
			StatusSetMessage(context, "Computing values...");

			# Loop on region to calculate statistics.
			local numeric lin, col;
			foreach targetRaster[lin, col] in reg {
				if (!IsNull(targetRaster)) {
					if (count == 0) {
						max = targetRaster;
						min = targetRaster;
						}
					else if (targetRaster > max) {
						max = targetRaster;
						}
					else if (targetRaster < min) {
						min = targetRaster;
						}
					sum += targetRaster;
					sumsqr += sqr(targetRaster);
					count += 1;
					}

				# Surface area is estimated by by adding the areas of triangles created
				# by the current cell, the cell below it, the cell to the right of it,
				# and the cell to the lower right of it.
				# Estimate over null cells by keeping the last known value.
				if (!IsNull(targetRaster))
					current = targetRaster;
				if (!IsNull(targetRaster[lin,col+1]))
					right = targetRaster[lin,col+1];
				if (!IsNull(targetRaster[lin+1,col]))
					down = targetRaster[lin+1,col];
				if (!IsNull(targetRaster[lin+1,col+1]))
					downright = targetRaster[lin+1,col+1];
				surface += .5*sqrt(sqr(yscale*current*zscale-yscale*right*zscale)
								+sqr(xscale*current*zscale-xscale*down*zscale)
								+sqr(xscale*yscale));
				surface += .5*sqrt(sqr(yscale*downright*zscale-yscale*right*zscale)
								+sqr(xscale*downright*zscale-xscale*down*zscale)
								+sqr(xscale*yscale));
				cells += 1;
				}
			CloseRaster(targetRaster);

			# Avoid division by zero when calculating mean and standard deviation.
			if (count > 1) {
				mean = sum / count;
				stdDev = sqrt((sumsqr - sqr(sum) / count) / (count - 1));
				area = reg.GetArea();
				perimeter = reg.GetPerimeter();
				centroid = reg.GetCentroid();
				}

			cbRedraw();

			# Destroy the status bar
			StatusContextDestroy(context);
			StatusDialogDestroy(status);
			}
		}
	}

# Called when a unit type is selected.
proc cbDistUnits(class Widget parent, unit$) {
	distScale = GetUnitConvDist("meters", unit$);
	cbRedraw();
	}

# Called when a unit type is selected.
proc cbAreaUnits(class Widget parent, unit$) {
	areaScale = GetUnitConvArea("square meters", unit$);
	cbRedraw();
	}

# Called when the save button is pressed.  Saves statistics to text file.
proc cbSave() {
	local class FILE outfile;
	local numeric larea, lperimeter, lsurface;

	# Scale the values to specified units.
	larea = areaScale * area;
	lperimeter = distScale * perimeter;
	lsurface = areaScale * surface;

	# Open output file, write to it, and close it
	outfile = GetOutputTextFile(_context.ScriptDir, "Choose file...", "txt");
	fprintf(outfile, "Raster: %s\nCells: %d\nNull Cells: %d\nMinimum: %.2f\nMaximum: %.2f\nMean: %.2f\nStandard Deviation: %.2f\nArea: %.2f\nPerimeter: %.2f\nCentroid: %.2f, %.2f\nSurface Area: %.2f",
							rasterName$, count, cells - count, min, max, mean, stdDev, larea, lperimeter, centroid.x, centroid.y, lsurface);
	fprintf(outfile, "\nDistance Units: %s\nArea Units: %s\n\n", distMenu.value, areaMenu.value);
	fclose(outfile);
	}

# Called when the user presses the clear region button.
proc cbClearRegion() {
	vectorLayer.UnHighlightAllElements();
	numPolys = 0;
	}

# Called when the close button is pressed.  Closes the dialogs.
proc cbClose() {
	pointTool.Managed = 0;
	pointTool.HasPosition = 0;
	DialogClose(form);
	if (setDefaultWhenClose) {
		setDefaultWhenClose = false;
		View.SetDefaultTool();
		}
	}

# Called when the user selects plus region.
proc cbPlusRegion() {
	regionMode$ = "plus";
	}

# Called when the user selects minus region.
proc cbMinusRegion() {
	regionMode$ = "minus";
	}

# 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) {
		WidgetAddCallback(Layout.GroupSelectedCallback, cbGroup);
		group = Layout.ActiveGroup;
		}
	else
		group = Group;
	WidgetAddCallback(group.LayerSelectedCallback, cbLayer);

	# Set up tool dialog.
	form = CreateFormDialog("Region Statistics");
	form.marginHeight = 2;
	form.marginWidth = 2;
	WidgetAddCallback(form.Shell.PopdownCallback, cbClose);

	# add region mode (+,-) region icons
	# set the icons to initial state - plus region
	plusicon = CreateToggleButtonItem("Add to region", cbPlusRegion);
	plusicon.IconClass = "standard";
	plusicon.IconName = "add_select";
	plusicon.OneOfMany = true;

	minusicon = CreateToggleButtonItem("Subtract from region", cbMinusRegion);
	minusicon.IconClass = "standard";
	minusicon.IconName = "minus_select";
	minusicon.OneOfMany = true;

	plusMinus = CreateForm(form);
	CreateIconButtonRow(plusMinus, plusicon, minusicon);
	plusMinus.TopWidget = form;
	plusMinus.LeftWidget = form;

	clearicon = CreateIconPushButton(form, "standard", "delete", "Clear regions");
	clearicon.TopWidget = form;
	clearicon.leftWidget = plusMinus;
	WidgetAddCallback(clearicon.ActivateCallback, cbClearRegion);

	# Drawing area for displaying text.
	da = CreateDrawingArea(form, 185, 301);
	da.topWidget = plusMinus;
	da.leftWidget = form;
	da.rightWidget = form;
	WidgetAddCallback(da.ExposeCallback, cbRedraw);

	# Separator between output and unit tools.
	line1 = CreateHorizontalSeparator(form);
	line1.topWidget = da;
	line1.leftWidget = form;
	line1.rightWidget = form;
	line1.bottomOffset = 2;

	# Menus for selecting units.
	distMenu = CreateUnitOptionMenu(form, "distance_units_c", cbDistUnits, 2, 0);
	distMenu.topWidget = line1;
	distMenu.leftWidget = form;

	areaMenu = CreateUnitOptionMenu(form, "area_units_c", cbAreaUnits, 1, 0);
	areaMenu.topWidget = distMenu;
	areaMenu.leftWidget = form;

	# Separator between unit tools and buttons.
	line2 = CreateHorizontalSeparator(form);
	line2.topWidget = areaMenu;
	line2.leftWidget = form;
	line2.rightWidget = form;
	line2.topOffset = 2;

	# Allows user to save statistics to text file.
	saveButton = CreatePushButtonItem("Save As...", cbSave);

	# Closes the dialog.
	closeButton = CreatePushButtonItem("Close", cbClose);

	# Row of buttons.
	buttonRow = CreateButtonRow(form, saveButton, closeButton);
	buttonRow.topWidget = line2;
	buttonRow.leftWidget = form;
	buttonRow.rightWidget = form;

	# Add point tool.
	pointTool = ViewCreatePointTool(View);
	ToolAddCallback(pointTool.ActivateCallback, cbToolApply);

	}  # end of OnInitialize 
 
# Called when tool is to be destroyed, will not be called if tool was never activated.
func OnDestroy () {
	pointTool.Managed = 0;
	DestroyGC(gc);
	DestroyWidget(form);
	}  # end of OnDestroy 
 
# Called when tool is activated.
func OnActivate () {
	pointTool.Managed = 1;
	pointTool.HasPosition = 0;
	plusicon.Selected = 1;
	if (checkLayer())
		cbClearRegion();
	DialogOpen(form);
	if (gc == 0)
		gc = CreateGCForDrawingArea(da);
	cells = 0; min = 0; max = 0; mean = 0; stdDev = 0; sum = 0; sumsqr = 0; count = 0; surface = 0; area = 0; perimeter = 0;
	centroid.x = 0; centroid.y = 0;
	distScale = 1;
	areaScale = 1;
	distMenu.value = "meters";
	areaMenu.value = "square meters";
	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


Back Home ©MicroImages, Inc. 2013 Published in the United States of America
11th Floor - Sharp Tower, 206 South 13th Street, Lincoln NE 68508-2010   USA
Business & Sales: (402)477-9554  Support: (402)477-9562  Fax: (402)477-9559
Business info@microimages.com  Support support@microimages.com  Web webmaster@microimages.com

25 March 2009

page update: 26 May 11