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


Rastprof.sml

See other examples of Tool and Macro scripts ...


# RASTPROF.SML

# View ToolScript

# This sample toolscript allows the user to draw a profile line in the View using a 2-point line tool.
# It accumulates the raster values from the active raster along the line and then draws a
# graph showing the profile of the raster along the line.  The profile can be constructed using
# raw raster values or values averaged over a 3 x 3, 5 x 5, or 7 x 7 focal area.
#
# The active layer must be a continuous-value raster; composite rasters cannot be used.

# Requires TNT version 2008:74 or later.

	# The following symbols are predefined
	#    class GRE_VIEW View            {use to access the view the tool script is attached to}
	#    class GRE_GROUP Group          {use to access the group being viewed if the script is run from a group view}
	#    class GRE_LAYOUT Layout        {use to access the layout being viewed if the script is run from a layout view}
	#    numeric ToolIsActive           Will be 0 if tool is inactive or 1 if tool is active
	#
	# The following values are also predefined and are valid when the various On...()
	# functions are called which deal with pointer and keyboard events.
	#    numeric PointerX            Pointer X coordinate within view in pixels
	#    numeric PointerY            Pointer Y coordinate within view in pixels
	#    numeric ShiftPressed        1 if  key being pressed or 0 if not
	#    numeric CtrlPressed         1 if  key being pressed or 0 if not
	#    numeric LeftButtonPressed   1 if left pointer button pressed or 0 if not
	#    numeric RightButtonPressed  1 if right pointer button pressed or 0 if not
	#    numeric MiddleButtonPressed 1 if middle pointer button pressed or 0 if not
	#

### GLOBAL VARIABLES
class GRE_GROUP activeGroup;				# the active group in the View
class GRE_LAYER rasterLayer;		# active layer containing the target raster
class RVC_RASTER targetRaster;	# target raster object

class GUI_DLG dlgwin;
class GUI_CANVAS canvas;			# drawing canvas in GUI Dialog window
class GC gc;							# graphics context for the canvas
class GUI_GADGET_SEGMENT profileLine;			# tool for drawing 2-point line in View
class STRING rasterName$;

numeric doGraph, hasNull;
class POINT2D startpoint;
class POINT2D endpoint;
array numeric value[1000000];
array numeric draw[1000000];
array numeric graphx[3], graphy[3];		# arrays for x & y coordinates of graph axes
numeric min, max, count, nullVal;
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 (activeGroup.ActiveLayer.Type == "") {
		rasterName$ = "Group has no layers!";
		}
	else {
		if (activeGroup.ActiveLayer.Type == "Raster") {
			rasterLayer = activeGroup.ActiveLayer;
			DispGetRasterFromLayer(targetRaster, rasterLayer);
			# Check for null values
			if (HasNull(targetRaster)) {
				hasNull = 1;
				nullVal = NullValue(targetRaster);
				}
			else
				hasNull = 0;

			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!";
				}
			else {
				rasterName$ = rasterLayer.Name;
				valid = true;
				}
			}
		else
			rasterName$ = "Not a raster!";
		}
	return valid;
	}

# Callback for drawing area expose.  Draws text and graph.
proc cbRedraw()
	{
	local class POLYLINE graphLine;	# polyline used to draw profile line(s)
	local class POINT2D graphPt;		# point for the current profile line vertex

	gc = canvas.CreateGC();

	# Clear the drawing area and redraw text.
	gc.SetColorRGB(255, 255, 255, 255);
	gc.FillRect(0, 0,  canvas.GetWidth(), canvas.GetHeight() );
	gc.SetColorName("black");

	gc.DrawTextSetFont("ARIALBD.TTF");
	gc.DrawTextSetHeight(12);
	gc.DrawTextSimple(sprintf("Raster: %s", rasterName$), 0, 10);

	if (doGraph == 0) return;

	local string min$, max$;
	local numeric size;

	### Draw graph axes
	min$ = sprintf("%d", min);
	max$ = sprintf("%d", max);
	size = strlen(max$);

	# set coordinates of upper end of y-axis
	graphx[1] = size * 6.5 + 5;
	graphy[1] = 20;

	# origin of x and y axes
	graphx[2] = graphx[1];
	graphy[2] = canvas.GetHeight() - 15;

	# right end of x-axis
	graphx[3] = canvas.GetWidth() - 5;
	graphy[3] = graphy[2];

	# draw the axes
	gc.DrawPolyLine(graphx, graphy, 3);

	gc.DrawTextSetFont("stork");
	gc.DrawTextSetHeight(10);

	gc.DrawTextSimple(max$, 0, graphy[1]+10);
	gc.DrawTextSimple(min$, (size - strlen(min$)) * 6.5, graphy[2]);
	gc.DrawTextSimple(sprintf("%d, %d", startpoint.x, startpoint.y), graphx[1], canvas.GetHeight() - 3);
	local string str$ = sprintf("%d, %d", endpoint.x, endpoint.y);
	gc.DrawTextSimple(str$, graphx[3] - strlen(str$) * 6.5, canvas.GetHeight() - 3);

	gc.SetColorName("magenta");	# color for drawing profile line

	local numeric xscale, yscale, prevnull;
	xscale = (graphx[3] - graphx[2] + 1) / (count - 1);
	yscale = (graphy[2] - graphy[1]) / (max - min);

	### Draw profile

	# add first profile point to the initial polyline
	if (value[1] < 0 || value[1] >= 0)	# if current value is not null
		{
		if (max - min == 0)		# all values are the same; set point at left end of horizontal profile line
			{
			graphPt.x = graphx[2];		graphPt.y = graphy[1] + (graphy[2]-graphy[1])*.5;
			}
		else							# set point at left end of profile line (on y-axis)
			{
			graphPt.x = graphx[2];	graphPt.y = graphy[2] - (value[1] - min) * yscale;
			}
		graphLine.AppendVertex(graphPt);		# add point to profile polyline
		}

	# loop through remaining items in the profile value array to draw profile line, leaving
	# gaps across areas of null cells (if any)
	local numeric i;
	for i = 2 to count
		{
		if (value[i] < 0 || value[i] >= 0)	# current value is not null
			{
			if (!(value[i-1] < 0 || value[i-1] >= 0))		# previous value was null; start new profile line segment
				{
				if (max - min == 0)		# all values are the same; set point at left edge of new segment
					{
					graphPt.x = graphx[2] + (i - 1) * xscale;
					graphPt.y = graphy[1] + (graphy[2] - graphy[1]) * .5;
					}
				else			# set point at left end of new segment of profile line
					{
					graphPt.x = graphx[2] + (i - 1) * xscale;
					graphPt.y = graphy[2] - (value[i] - min) * yscale;
					}
				graphLine.AppendVertex(graphPt);		# add point to profile polyline
				}
			else				# previous value was not null, continue current profile
				{
				if (max - min == 0)	# all values are the same; set point for horizontal profile
					{
					graphPt.x = graphx[2] + (i - 1) * xscale;
					graphPt.y = graphy[1] + (graphy[2] - graphy[1]) * .5;
					}
				else						# compute current point position on profile line
					{
					graphPt.x = graphx[2] + (i - 1) * xscale;
					graphPt.y = graphy[2] - (value[i] - min) * yscale;
					}
				graphLine.AppendVertex(graphPt);	# add point to profile polyline
				}
			}
		else			# current value is null
			{
			if (value[i-1] < 0 || value[i-1] >= 0)		# previous value is not null;
				{
				gc.DrawPolyLine2(graphLine);		# draw polyline for current profile segment to edge of this null area
				graphLine.Clear();					# clear polyline to start new profile segement at next non-null value
				}
			}
		}
	gc.DrawPolyLine2(graphLine);
	canvas.Refresh();
	graphLine.Clear();
	}

# Callback for when the active layer changes.
proc cbLayer()
	{
	checkLayer();
	cbRedraw();
	}

# Callback for when the active group changes.
proc cbGroup()
	{
	activeGroup = Layout.ActiveGroup;
	WidgetAddCallback(activeGroup.LayerSelectedCallback, cbLayer);
	cbLayer();
	}

# Callback for when user clicks the right mouse button on the line segment tool
proc cbToolApply()
	{
	if (checkLayer() )
		{
		local numeric avgSize = StrToNum(dlgwin.GetCtrlValueStr("avgSize") );

		# get coordinate transformation from screen to layer coordinates
		# (raster column and line coordinates)
		local class TRANS2D_MAPGEN trans;
		trans = View.GetTransLayerToScreen(rasterLayer, 1);

		startpoint = profileLine.start;
		endpoint = profileLine.end;

		# convert start and end point to view coordinates
		startpoint = trans.ConvertPoint2DFwd(startpoint);
		endpoint = trans.ConvertPoint2DFwd(endpoint);

		# Get x and y step values for sampling raster cell values along profile line
		local numeric ystep, xstep;
		local class POINT2D cursor;
		cursor = startpoint;
		count = 0;
		ystep = endpoint.y - startpoint.y;
		xstep = endpoint.x - startpoint.x;

		if (xstep == 0 && ystep == 0)			# profile start and end at same position
			return;

		# use the x/y extents of the profile line to compute step distance along line
		if (abs(xstep) > abs(ystep)) {
			ystep = ystep / abs(xstep);
			xstep = xstep / abs(xstep);
			if (ystep == 0) {
				count = abs(endpoint.x - startpoint.x);
				}
			else
				count = abs((endpoint.y - startpoint.y) / ystep);
			}
		else {
			xstep = xstep / abs(ystep);
			ystep = ystep / abs(ystep);
			if (xstep == 0) {
				count = abs(endpoint.y - startpoint.y);
				}
			else
				count = abs((endpoint.x - startpoint.x) / xstep);
			}
		count = count + 1;

		doGraph = 1;

		max = -1000000;
		min = 1000000;

		# Loop on line to generate point list.
		local numeric i;
		for i = 1 to count {

			if (avgSize == 1) then		# no averaging for raster values
				value[i] = targetRaster[round(cursor.y), round(cursor.x)];

			else		# use FocalMean function to get mean value for averaging area
				value[i] = FocalMean(targetRaster, avgSize, avgSize, round(cursor.y), round(cursor.x))

			# If the raster value was retrieved from a null cell or a coordinate
			# outside the raster extents, value[i] will be 'not a number'.
			# Therefore testing if it is < 0 or >= 0 determines whether it is
			# a valid value
			if (value[i] < 0 || value[i] >= 0)
				{
				if (value[i] > max)
					max = value[i];
				if (value[i] < min)
					min = value[i];
				}
			cursor.x = cursor.x + xstep;
			cursor.y = cursor.y + ystep;
			}
		if (max == -1000000 && min == 1000000)
			{
			max = 0;
			min = 0;
			}

		cbRedraw();
		}
	}		# end of cbToolApply


# Called when the close button is pressed.  Closes the dialogs.
proc cbClose()
	{
	profileLine.Managed = 0;
	dlgwin.Close(0);
	if (setDefaultWhenClose) {
		setDefaultWhenClose = false;
		View.SetDefaultTool();
		}
	}

	# The following script functions will be called (if used in the script) when
	# the appropriate action or event occurs as described in the comments before each.
	# To use a function, uncomment the lines containing the 'func' definition
	# and ending brace '}' by removing the leftmost '#' on the line and add the
	# function code between the two lines.


# Called the first time the tool is activated.
# If the tool implements a dialog it should be created (but not displayed) here.
proc OnInitialize ()
	{
	if (Layout)
		{
		WidgetAddCallback(Layout.GroupSelectedCallback, cbGroup);
		activegroup = Layout.ActiveGroup;
		}
	else
		activeGroup = Group;
	WidgetAddCallback(activegroup.LayerSelectedCallback, cbLayer);

	# Add the 2-point line tool (segment)
	profileLine = ViewCreateLineTool(View);
	ToolAddCallback(profileLine.ApplyCallback, cbToolApply);

	# string with dialog specification
	xml$ = '
	
	
		
			
				
			
			
				
				
					
					
					
					
				
			
		
	';

	### parse XML string; returns an error code (number < 0 ) if there are syntax errors
	local class XMLDOC doc;
	err = doc.Parse(xml$);
	if (err < 0)
		{
		PopupError(err); # Popup an error dialog. "Details" button shows syntax errors.
		Exit();
		}

	### declare class instance for the dialog element in the XML structure
	### and get the dialog handle from the XML structure.
	### Pop up an error dialog and exit if the dialog ID can't be found in the XML.
	class XMLNODE dlgnode;
	dlgnode = doc.GetElementByID("rastprof");

	if (dlgnode == 0)
		{
		PopupMessage("Could not find dialog node in XML document");
		Exit();
		}

	### set the XML structure in memory as the source for the dialog.
	dlgwin.SetXMLNode(dlgnode);

	err = dlgwin.CreateModeless();
	if (err < 0)
		{
		PopupError(err); # Popup an error dialog. "Details" button shows syntax errors.
		Exit();
		}

	# get handle for drawing canvas in dialog window
	canvas = dlgwin.GetCtrlByID("canvas");

	} # end of OnInitialize

# Called when tool is to be destroyed, will not be called if tool was never activated.
# If the tool implements a dialog it should be destroyed here.
# proc OnDestroy () {
# } # end of OnDestroy

# Called when tool is activated.
# If the tool implements a dialog it should be "managed" (displayed) here.
proc OnActivate ()
	{
	local numeric err;
	checkLayer();

	profileLine.Managed = 1;
	profileLine.HasPosition = 0;
	err = dlgwin.Open();

	cbRedraw();
	setDefaultWhenClose = true;
	}  # end of OnActivate

# Called when tool is deactivated (usually when switching to another tool).
# If the tool implements a dialog it should be "unmanaged" (hidden) here.
proc OnDeactivate ()
	{
	setDefaultWhenClose = false;
	cbClose();
	}  # end of OnDeactivate

# Called when tool is to be 'suspended' during a redraw operation.
# proc OnSuspend () {
# }  # end of OnSuspend

# Called when tool is to be 'resumed' after a redraw operation.
# If the tool displays any graphics they should be updated by this function.
# proc OnResume () {
# }  # end of OnResume

# Called when user presses 'left' pointer/mouse button.
# proc OnLeftButtonPress () {
# }  # end of OnLeftButtonPress

# Called when user presses 'right' pointer/mouse button.
#proc OnRightButtonPress () {
#}  # end of OnRightButtonPress

# Called when user presses 'middle' pointer/mouse button.
# proc OnMiddleButtonPress () {
# }  # end of OnMiddleButtonPress

# Called when user releases 'left' pointer/mouse button.
# proc OnLeftButtonRelease () {
# }  # end of OnLeftButtonRelease

# Called when user releases 'right' pointer/mouse button.
# proc OnRightButtonRelease () {
# }  # end of OnRightButtonRelease

# Called when user releases 'middle' pointer/mouse button.
# proc OnMiddleButtonRelease () {
# }  # end of OnMiddleButtonRelease

# Called when user moves cursor if no button being pressed
# proc OnPointerMoveNoButton () {
# }  # end of OnPointerMoveNoButton

# Called when user moves cursor while holding down button
# proc OnPointerMoveWithButton () {
# }  # end of OnPointerMoveWithButton

# Called when cursor enters window associated with view.
# proc OnEnterWindow () {
# }  # end of OnEnterWindow

# Called when cursor leaves window associated with view.
# proc OnLeaveWindow () {
# }  # end of OnLeaveWindow

# Called when user presses 'key' on keyboard.
# proc OnKeyPress (key) {
# }  # end of OnKeyPress

 


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