#######################################
# BOXCAR2.SML Demonstration Script
# Sample script for Building Dialogs in SML
#
# Keith Ghormley, MicroImages, Inc.
# Revised for TNTmips SML version 6.80
# by Randy Smith, MicroImages, Inc.
# Script shows steps needed to create a sample application
# with a dialog window incorporating a view of geospatial
# data.
# Example is an interactive "boxcar" classification of
# a set of three input rasters. The user specifies a
# range of raster values for each input raster, and the
# script identifies cells whose value sets fall within
# the specified ranges.
# The three input rasters (identified as Red, Green, and
# Blue) are used to make a color composite for display.
# A dialog window incorporates the view and prompt fields
# for entering limit values for the boxcar classification
# ranges. A temporary binary classification raster is
# used to hold the result of the classification and is
# displayed over the input composite with "0" cells
# transparent and "1" cells in yellow. This raster is
# computed and display when the user presses the Process
# button. Pressing the Clear button or entering any new
# limit values removes the class layer from the view and
# resets all values to 0. The Save button allows the
# user to save the temporary class raster in a project file.
# The close button closes the dialog and frees all resources.
clear();
########################################################
# Class instances needed in procedures
class GRE_GROUP gp; # spatial group for display.
class GRE_VIEW view; # view that displays the group.
class XmForm bcwin; # parent form for window.
class GRE_LAYER_RASTER templayer; # layer handle for class raster.
class RVC_COLORMAP cPalette; # handle for color palette for
# class raster.
class PROMPTNUM redHI, redLO, greenHI, greenLO, blueHI, blueLO;
# class instances for the editable numeric fields in the dialog
########################################################
# Global Variables
numeric numlins, numcols;
string rasttype$;
numeric gmRed, maxRed, minRed;
numeric gmGreen, maxGreen, minGreen;
numeric gmBlue, maxBlue, minBlue;
numeric rLO, rHI, gLO, gHI, bLO, bHI;
numeric count, templayerexists;
class RASTER Red, Green, Blue; # variables for input rasters
class RASTER TempRed, TempGreen, TempBlue; # temporary rasters for contrast-
# adjusted versions of input rasters
class RASTER TempComp; # variable for temporary composite raster for display
class RASTER TempClass; # variable for temporary class raster
class RASTER ClassRast; # variable for saved class raster
########################################################
# Define procedures.
# Called when Clear button is pressed or when
# range values are changed.
proc OnClear() {
if (templayerexists == 1) {
LayerDestroy(templayer);
ViewRedraw(view,0);
templayerexists = 0;
for each TempClass {
if (TempClass == 1) then
TempClass = 0;
}
}
}
# Called when new Red High value is input.
proc OnR_HI() {
rHI = redHI.value;
OnClear();
}
# Called when new Red Low value is input.
proc OnR_LO() {
rLO = redLO.value;
OnClear();
}
# Called when new Green High value is input.
proc OnG_HI() {
gHI = greenHI.value;
OnClear();
}
# Called when new Green Low value is input.
proc OnG_LO() {
gLO = greenLO.value;
OnClear();
}
# Called when new Blue High value is input.
proc OnB_HI() {
bHI = blueHI.value;
OnClear();
}
# Called when new Blue Low value is input.
proc OnB_LO() {
bLO = blueLO.value;
OnClear();
}
# Called when Process button is pressed.
proc OnProcess() {
count = 0;
ViewSetMessage(view,"Processing...");
for each TempClass {
if ( (Red <= rHI) and (Red >= rLO) and
(Green <= gHI) and (Green >= gLO) and
(Blue <= bHI) and (Blue >= bLO) )
then {
TempClass = 1;
count = count + 1;
}
}
if (count == 0) {
OnClear();
ViewSetMessage(view,"No cells fall in specified ranges.");
PopupMessage("No cells fall in specified ranges. Adjust ranges and process again.");
}
else {
templayer = GroupQuickAddRasterVar(gp,TempClass);
templayer.NullCellsTransparent = 1;
templayer.ColorMap = cPalette;
ViewRedraw(view,0);
templayerexists = 1;
}
}
# Called when Save button is pressed.
proc OnSave() {
GetOutputRaster(ClassRast,numlins,numcols,"binary");
for each ClassRast {
ClassRast = TempClass;
}
CopySubobjects(TempClass,ClassRast,"ALL");
}
# Called when Close button is pressed or when the "X" close
# button on the title bar is pressed.
proc OnClose() {
DestroyWidget(bcwin);
GroupDestroy(gp);
CloseRaster(TempComp); CloseRaster(TempClass);
CloseRaster(Red); CloseRaster(Green); CloseRaster(Blue);
}
# Called when dialog is destroyed.
# Can be either by the "Close" menu item or by us
# calling DestroyWidget() above.
proc OnDestroy() {
Exit();
}
##########################################################
# Main program
##########################################################
# Get input rasters.
PopupMessage("Select three processing bands for boxcar classification.");
GetInputRaster(Red);
numlins = NumLins(Red); numcols = NumCols(Red); rasttype$ = RastType(Red);
GetInputRaster(Green,numlins,numcols,rasttype$);
GetInputRaster(Blue,numlins,numcols,rasttype$);
# Create temporary composite raster from input for display.
# (There is currently no SML function to display an RGB raster set).
# The function that creates a composite raster requires an output filename,
# object name, and description. We will use the class information from
# the temporary raster to provide the filename, object name, and object
# description to the conversion function.
# The conversion function also ignores contrast tables, so we will first
# create contrast-enhanced versions of the input rasters by applying
# the last-used contrast subobject for each raster.
class RASTER TempComp;
CreateTempRaster(TempComp,numlins,numcols,"24-bit color RGB");
CreateTempRaster(TempRed,numlins,numcols,"8-bit unsigned");
CreateTempRaster(TempGreen,numlins,numcols,"8-bit unsigned");
CreateTempRaster(TempBlue,numlins,numcols,"8-bit unsigned");
RasterApplyContrast2(Red,TempRed,"Subobject");
RasterApplyContrast2(Green,TempGreen,"Subobject");
RasterApplyContrast2(Blue,TempBlue,"Subobject");
RasterRGBToComposite(TempRed,TempGreen,TempBlue,TempComp,TempComp.$Info.Filename,
TempComp.$Info.Name,TempComp.$Info.Desc);
CopySubobjects(Red,TempComp,"georef");
CreatePyramid(TempComp,0);
# Create temporary binary raster for boxcar class.
# Will be displayed over the composite.
CreateTempRaster(TempClass,numlins,numcols,"binary");
CopySubobjects(Red,TempClass,"georef");
# Create color palette subobject for binary class raster.
# Define one palette color with transparency.
class Color clsclr;
clsclr.red = 100;
clsclr.green = 100;
clsclr.blue = 0;
clsclr.transp = 0;
# Set index color 1 and write color palette to temporary raster.
ColorMapSetColor(cPalette,1,clsclr);
ColorMapWriteToRastVar(TempClass,cPalette,"Color Palette","");
##########################################################
# Get mean, max, and min values from input rasters.
gmRed = int(GlobalMean(Red));
maxRed = GlobalMax(Red);
minRed = GlobalMin(Red);
gmGreen = int(GlobalMean(Green));
maxGreen = GlobalMax(Green);
minGreen = GlobalMin(Green);
gmBlue = int(GlobalMean(Blue));
maxBlue = GlobalMax(Blue);
minBlue = GlobalMin(Blue);
# Set initial cell value ranges for boxcar classification.
rLO = gmRed - 10;
rHI = gmRed + 10;
gLO = gmGreen - 10;
gHI = gmGreen + 10;
bLO = gmBlue - 10;
bHI = gmBlue + 10;
#########################################################
# Create dialog window for boxcar classification.
#########################################################
gp = GroupCreate();
bcwin = CreateFormDialog("Boxcar Classification");
WidgetAddCallback(bcwin.Shell.PopdownCallback, OnClose);
WidgetAddCallback(bcwin.DestroyCallback, OnDestroy);
# Create pushbutton items for Process, Clear, Save, and Close.
class PUSHBUTTONITEM btnItemProcess;
class PUSHBUTTONITEM btnItemClear;
class PUSHBUTTONITEM btnItemSave;
class PUSHBUTTONITEM btnItemClose;
btnItemProcess = CreatePushButtonItem("Process",OnProcess);
btnItemClear = CreatePushButtonItem("Clear",OnClear);
btnItemSave = CreatePushButtonItem("Save",OnSave);
btnItemClose = CreatePushButtonItem(" Close ",OnClose);
# Create button row for pushbuttons and attach to bottom
# of dialog window.
class XmForm btnrow;
btnrow = CreateButtonRow(bcwin,btnItemProcess,btnItemClear,btnItemSave,btnItemClose);
btnrow.BottomWidget = bcwin;
btnrow.RightWidget = bcwin;
btnrow.LeftWidget = bcwin;
# Create separator line above button row.
class XmSeparator sepline;
sepline = CreateHorizontalSeparator(bcwin);
sepline.TopOffset = 4;
sepline.LeftWidget = bcwin;
sepline.RightWidget = bcwin;
sepline.BottomWidget = btnrow;
# Create RowColumn widget with to hold min-max labels
# and prompt fields for hi-lo values. Set orientation
# to horizontal so the column parameter sets the number of
# rows to 4 and to fill in the row direction first.
class XmRowColumn promptrc;
promptrc = CreateRowColumn(bcwin,4);
promptrc.Orientation = "HORIZONTAL";
promptrc.BottomWidget = sepline;
# Create labels in RowColumn widget for Min and Max raster values.
class XmLabel redMin, greenMin, blueMin;
class XmLabel redMax, greenMax, blueMax;
redMin = CreateLabel(promptrc, sprintf(" Min. Red: %d",minRed) );
greenMin = CreateLabel(promptrc, sprintf(" Min. Green: %d",minGreen) );
blueMin = CreateLabel(promptrc, sprintf(" Min. Blue: %d",minBlue) );
redMax = CreateLabel(promptrc, sprintf(" Max. Red: %d",maxRed) );
greenMax = CreateLabel(promptrc, sprintf(" Max. Green: %d",maxGreen) );
blueMax = CreateLabel(promptrc, sprintf(" Max. Blue: %d",maxBlue) );
# Create prompt fields in the same RowColumn widget.
# Add callbacks for change in value.
redLO = CreatePromptNum(promptrc," Red Low: ",3,0,gmRed-10,minRed,maxRed);
WidgetAddCallback(redLO.ValueChangedCallback,OnR_LO);
greenLO = CreatePromptNum(promptrc," Green Low: ",3,0,gmGreen-10,minGreen,maxGreen);
WidgetAddCallback(greenLO.ValueChangedCallback,OnG_LO);
blueLO = CreatePromptNum(promptrc," Blue Low: ",3,0,gmBlue-10,minBlue,maxBlue);
WidgetAddCallback(blueLO.ValueChangedCallback,OnB_LO);
redHI = CreatePromptNum(promptrc," Red High: ",3,0,gmRed+10,minRed,maxRed);
WidgetAddCallback(redHI.ValueChangedCallback,OnR_HI);
greenHI = CreatePromptNum(promptrc," Green High: ",3,0,gmGreen+10,minGreen,maxGreen);
WidgetAddCallback(greenHI.ValueChangedCallback,OnG_HI);
blueHI = CreatePromptNum(promptrc," Blue High: ",3,0,gmBlue+10,minBlue,maxBlue);
WidgetAddCallback(blueHI.ValueChangedCallback,OnB_HI);
# Adjust widths of prompt labels to align them better.
redLO.label.width = redHI.label.width;
redLO.label.Alignment = "ALIGNMENT_END";
greenLO.label.width = greenHI.label.width;
greenLO.label.Alignment = "ALIGNMENT_END";
blueLO.label.width = blueHI.label.width;
blueLO.label.Alignment = "ALIGNMENT_END";
# Create view in bcwin to display input rasters and class overlay.
# A view has its own XmForm widget accessed as a class member "Form".
# We add the view last because the last widget added is the only one
# that resizes automatically if the parent dialog is resized.
# If the view were added earlier, the last button row added would
# be the widget that would automatically resize.
view = GroupCreateView(gp,bcwin,"",500,400,"DestroyOnClose,NoStatusLine,NoScalePosLine");
bcwin.BottomWidget = promptrc;
##########################################################
# Open window and add composite from input rasters to view.
DialogOpen(bcwin);
GroupQuickAddRasterVar(gp,TempComp);
ViewRedrawFull(view);
WaitForExit();
# End of main process.