## RasterIntervals.sml
## Sample script for Introduction to Geospatial Scripting.
## Standalone script to categorize a grayscale raster into a
## specified number of grayscale-value intervals. The number of
## intervals and the distribution type (equal count or equal interval)
## can be specified. Separate dialogs are provided to set input
## parameters, view and edit the range values, and to preview the
## result. Script makes a categorical raster with a single value
## for each interval and a color palette.
class RASTER RastIn, RastClass; # class instances for input and output rasters
class RASTER Temp; # class instance for temporary raster for result preview
class COLORMAP palette; # class instance for color palette for output raster
numeric maxRast; # input raster maximum value
numeric minRast; # input raster minimum value
numeric globalRange; # global range of raster values
numeric numInterval; # number of intervals to create
numeric distribType; # flag for type of interval: 0 = equal range, 1 = equal count
numeric i, j; # counters for processing loops
numeric value; # current raster value in input
numeric globalNumCells; # number of non-null cells in raster
numeric counter; # counter for running count of cells
array numeric minRange[1]; # array to hold minimum boundary values for ranges
array numeric maxRange[1]; # array to hold maximum boundary values for ranges
array numeric cellCount[1]; # array to hold final cell count for each interval
array numeric cellPct[1]; # array to hold cell percentage for each interval
#### variables for color palette structure
string xmlPalette$;
class XMLDOC docColor;
### variables for dialog windows
string xmlmain$; # string variable for main dialog specification
class XMLDOC docmain; # class instance for parsed XML text containing main dialog specification
class XMLNODE nodemain; # class instance for dialog node in XML structure for main dialog window
class GUI_DLG dlgmain; # dialog class instance for main dialog window
numeric errXML, dlgreturn; # variables for error checking with main XML and dialog
string xmldistrib$; # string variable for Distribution dialog specification
class XMLDOC docdistrib; # class instance for parsed XML text containing Distribution dialog specification
class XMLNODE nodedistrib; # class instance for dialog node in XML structure for Distribution dialog window
class GUI_DLG dlgDistrib; # dialog class instance for Distribution dialog window
string xmlPreview$; # string variable for Preview dialog specification
class XMLDOC docPreview; # class instance for parsed XML text containing Preview dialog specification
class XMLNODE nodePreview; # class instance for dialog node in XML structure for Preview dialog window
class GUI_DLG dlgPreview; # dialog class instance for Preview window
class GRE_VIEW view; # class instance for the view in the Preview window
#####################################################################
######## Procedure and Function Definitions #######################
#####################################################################
#######################################################################
### Define function to return the class interval of the current raster
### value by comparison to range boundaries
func SetInterval(valueIn) {
for i = 1 to numInterval {
if (valueIn >= minRange[i] && valueIn <= maxRange[i]) then
return i;
}
}
########################################################################
### Define procedure to update cell counts and percentages for intervals
proc updateCounts (numeric indexStart, numeric indexEnd)
{
local numeric i, counter;
## reset cell counts for relevant intervals to 0
for i = indexStart to indexEnd
{
cellCount[i] = 0;
}
## loop through input raster to get cell count for each specified interval
for each RastIn
{
++ counter;
for i = indexStart to indexEnd
{
if (RastIn >= minRange[i] && RastIn <= maxRange[i]) then
++ cellCount[i];
}
}
# compute cell percentage for each interval
for i = indexStart to indexEnd
{
cellPct[i] = 100 * cellCount[i] / counter;
}
}
#####################################################
### Callback procedure to initally disable OK button
### on main dialog window when it opens
proc onOpenMain ()
{
dlgmain.SetOkEnabled( 0 );
}
#######################################################
### Callback procedure to select input grayscale raster
proc getRastIn ()
{
GetInputRaster( RastIn );
if ( RastIn.$Info.Type == "16-bit color RGB" or RastIn.$Info.Type == "16-bit color BGR"
or RastIn.$Info.Type == "24-bit color RGB" or RastIn.$Info.Type == "24-bit color BGR"
or RastIn.$Info.Type == "binary" or RastIn.$Info.Type == "32-bit float" or RastIn.$Info.Type == "64-bit float" )
{
PopupMessage( sprintf("Selected raster type is: %s. \n Please select a valid grayscale integer raster.", RastIn.$Info.Type) );
}
else
{
local string filename$, objname$, dlgtext$;
local numeric objnum;
local class GUI_CTRL_PUSHBUTTON runButton;
filename$ = GetObjectFileName( RastIn );
objnum = GetObjectNumber( RastIn );
objname$ = GetObjectName( filename$, objnum );
dlgtext$ = sprintf( "%s.%s / %s", FileNameGetName(filename$), FileNameGetExt(filename$), objname$ );
dlgmain.SetCtrlValueStr("inRastText", dlgtext$);
maxRast = GlobalMax(RastIn);
minRast = GlobalMin(RastIn);
globalRange = maxRast - minRast + 1;
runButton = dlgmain.GetCtrlByID("runButton");
runButton.SetEnabled(1);
}
}
########################################################
### Callback procedure to select output interval raster
proc getRastOut ()
{
local string filename$, objname$, dlgtext$;
local numeric objnum;
GetOutputRaster(RastClass, RastIn.$Info.NumLins, RastIn.$Info.NumCols, "8-bit unsigned");
filename$ = GetObjectFileName( RastClass );
objnum = GetObjectNumber( RastClass );
objname$ = GetObjectName( filename$, objnum );
dlgtext$ = sprintf( "%s.%s / %s", FileNameGetName(filename$), FileNameGetExt(filename$), objname$ );
}
#########################################################
### Procedure to make interval raster with color palette.
### Used for temporary preview raster and for output raster
proc makeIntervalRaster(class Raster Rast)
{
local class GUI_CTRL_COLORBUTTON colorbutton;
local class ColorMap palette;
local class COLOR color;
for each RastIn
{
value = RastIn;
Rast = SetInterval(value);
}
CreateHistogram(Rast, 0);
CreatePyramid(Rast);
CopySubobjects(RastIn, Rast, "GEOREF");
###############################################################
### create color palette for output raster from the colors in the
### distribution dialog
for i = 1 to numInterval
{
local string interval$ = NumToStr(i);
colorbutton = dlgDistrib.GetCtrlByID(sprintf("colorbut%s", interval$));
color = colorbutton.GetColor();
ColorMapSetColor(palette, i, color);
}
ColorMapWriteToRastVar(Rast, palette, "IntervalColors", "Color palette");
SetNull(Rast, 0);
}
###############################################################
### Callback procedure when Distribution dialog opens. Sets
### ioitial colors of colorbuttons before opening (there is no
### way to do this using the XML structure, so must access the GUI
### control class for the colorbutton directly. Since this dialog is
### modal, it isn't created until DoModal method is called, so buttons
### must be set using the dialog's OnOpen callback.
proc onOpenDistrib ()
{
### loop through the intervals to assign colors
for i = 1 to numInterval
{
local string interval$ = NumToStr(i);
# generate color as HIS and convert to RGB and store in COLOR class instance
class COLOR color;
class XMLNODE colorNode;
colorNode = docColor.GetElementByID(interval$);
color.red = colorNode.GetAttributeNum("red");
color.green = colorNode.GetAttributeNum("green");
color.blue = colorNode.GetAttributeNum("blue");
# get handle for relevant colorbutton control in dialog
class GUI_CTRL_COLORBUTTON colorbutton;
colorbutton = dlgDistrib.GetCtrlByID(sprintf("colorbut%s", interval$));
colorbutton.SetColor(color);
}
}
########################################################################
### Callback procedure for OK button on Distribution dialog.
### Writes values to the output raster and sets up the color palette.
proc onOKdistrib ()
{
###################################
### fill in values in output raster
getRastOut();
makeIntervalRaster(RastClass);
dlgDistrib.Close(0);
} # end onOKdistrib()
#########################################################################
### Callback procedure for Cancel button on Distribution dialog.
proc onCancelDistrib ()
{
dlgDistrib.Close(0);
}
################################################################
### Procedure called when Exit button on main dialog is pressed.
### Closes dialog and exits script.
proc onExit ()
{
dlgmain.Close(0);
Exit();
}
#################################################################
### Procedure called when Close button on Preview window is pressed.
proc onPreviewClose ()
{
dlgPreview.Close(0);
}
##################################################################
### Procedure called when the Preview dialog window opens
proc onPreviewOpen ()
{
view.Redraw();
}
#####################################################################
### Procedure called when Preview dialog is initialized. Used to create
### view within the dialog and to create a group to view the temporary raster.
proc onInitDialog ()
{
local class GUI_LAYOUT_PANE viewpane; # class instance for layout pane to contain the view
local class widget viewpaneWidget; # class for widget for layout pane to serve as parent for the view
local class GRE_GROUP viewgp; # class for group to be shown in the view
local class GRE_LAYER_RASTER tempLayer;
viewpane = dlgPreview.GetPaneByID("viewpane"); # get handle for layout pane from dialog
viewpaneWidget = viewpane.GetWidget(); # get parent Xm widget for pane
viewpaneWidget.Resizable = 1; # set parent widget to be resizable
viewgp = GroupCreate(); # create display group
tempLayer = GroupQuickAddRasterVar(viewgp, Temp); # add the Temp raster to the group
tempLayer.DataTip.Prefix = "Interval: ";
view = viewgp.CreateView(viewpaneWidget,"",450, 350, "NoCloseOption"); # create 2D view of group in dialog
#view.ScalePosVisible = 0; # hide scale/position report
# view.LegendView.Show = "Left";
}
######################################################################
### Procedure called when Preview Result button on Distribution dialog
### is pressed.
proc onPreview ()
{
CreateTempRaster(Temp, RastIn.$Info.NumLins, RastIn.$Info.NumCols, "8-bit unsigned");
makeIntervalRaster(Temp);
# dialog specification for Preview dialog window
xmlPreview$='<?xml version="1.0"?>
<root>
<dialog id="previewDlg" Title="Preview" Buttons="" HorizResize="Expand" VertResize="Expand" OnOpen="onPreviewOpen()">
<pane id="viewpane" Orientation = "vertical" HorizResize="Expand" VertResize="Expand"/>
<pane Orientation="horizontal" HorizAlign="right" HorizResize="Fixed" VertResize="Fixed">
<pushbutton Name=" Close " VertResize="Fixed" VertAlign="Bottom" OnPressed="onPreviewClose()"/>
</pane>
</dialog>
</root>';
# parse XML text for the dialog into memory;
# return an error code (number < 0 ) if there are syntax errors
errXML = docPreview.Parse(xmlPreview$);
if (errXML < 0)
{
PopupError(errXML); # Popup an error dialog. "Details" button shows syntax errors.
Exit();
}
# get the dialog element from the parsed XML document and
# show error message if the dialog element can't be found
nodePreview = docPreview.GetElementByID("previewDlg");
if (nodePreview == 0)
{
PopupMessage("Could not find dialog node in XML document");
Exit();
}
# Set the XML dialog element as the source for the GUI_DLG class instance
# we are using for the dialog window.
dlgPreview.SetXMLNode(nodePreview);
dlgPreview.SetOnInitDialog(onInitDialog);
dlgPreview.DoModal();
}
###########################################################
### Callback for edit of any interval Minimum value editnumber field
proc onChangeMin(class GUI_CTRL_EDIT_NUMBER this, numeric i)
{
local numeric j = i - 1;
local numeric val = this.GetValueNum();
local numeric prevMin, thisMax, prevRng, thisRng;
local class GUI_CTRL_LABEL prevRngLabel, thisRngLabel;
local class GUI_CTRL_LABEL prevCountLabel, thisCountLabel;
local class GUI_CTRL_LABEL prevPctLabel, thisPctLabel;
### check that new minimum is greater than previous interval minimum
### and less than its own interval maximum and reset if necessary
prevMin = dlgDistrib.GetCtrlValueNum(sprintf("editMin%d", j));
thisMax = dlgDistrib.GetCtrlValueNum(sprintf("editMax%d", i));
if ( val <= prevMin )
{
val = prevMin + 2;
this.SetValue( val, 0 );
}
else
{
if ( val > thisMax )
{
val = thisMax - 1;
this.SetValue( val, 0 );
}
}
# reset minimum value in minRange array
minRange[i] = val;
# reset maximum value of next lower interval in dialog and in maxRange array
maxRange[j] = minRange[i] - 1;
dlgDistrib.SetCtrlValueNum( sprintf("editMax%d", j), maxRange[j] );
# compute new ranges for j and i intervals and update labels on dialog
prevRng = val - prevMin;
thisRng = thisMax - val + 1;
prevRngLabel = dlgDistrib.GetCtrlByID( sprintf("labelRng%d", j) );
prevRngLabel.SetLabel( NumToStr(prevRng) );
thisRngLabel = dlgDistrib.GetCtrlByID( sprintf("labelRng%d", i) );
thisRngLabel.SetLabel( NumToStr(thisRng) );
# update counts and percentages
updateCounts(j, i);
prevCountLabel = dlgDistrib.GetCtrlByID( sprintf("labelCount%d", j) );
prevCountLabel.SetLabel( NumToStr(cellCount[j] ) );
thisCountLabel = dlgDistrib.GetCtrlByID( sprintf("labelCount%d", i) );
thisCountLabel.SetLabel( NumToStr(cellCount[i] ) );
prevPctLabel = dlgDistrib.GetCtrlByID( sprintf("labelPct%d", j) );
prevPctLabel.SetLabel( sprintf("%.2f", cellPct[j] ) );
thisPctLabel = dlgDistrib.GetCtrlByID( sprintf("labelPct%d", i) );
thisPctLabel.SetLabel( sprintf("%.2f", cellPct[i] ) );
} # end onChangeMin()
###########################################################
### Callback for edit of any interval Maximum value editnumber field
proc onChangeMax(class GUI_CTRL_EDIT_NUMBER this, numeric i)
{
local numeric j = i + 1;
local numeric val = this.GetValueNum(); # new value for editnumber field
local numeric thisMin, nextMax, thisRng, nextRng;
local class GUI_CTRL_LABEL thisRngLabel, nextRngLabel;
local class GUI_CTRL_LABEL thisCountLabel, nextCountLabel;
local class GUI_CTRL_LABEL thisPctLabel, nextPctLabel;
### check that new maximum is greater than its own interval minimum
### and less than the next interval maximum and reset if necessary
thisMin = dlgDistrib.GetCtrlValueNum( sprintf( "editMin%d", i ) );
nextMax = dlgDistrib.GetCtrlValueNum( sprintf( "editMax%d", j ) );
if ( val < thisMin )
{
val = thisMin + 1;
this.SetValue( val, 0 );
}
else
{
if ( val >= nextMax )
{
val = nextMax - 2;
this.SetValue( val, 0 );
}
}
# read new maximum value for interval from editnumber and reset value in maxRange array
maxRange[i] = val;
# reset minimum value of next higher interval in dialog and in minRange array
minRange[j] = maxRange[i] + 1;
dlgDistrib.SetCtrlValueNum(sprintf("editMin%d", j), minRange[j]);
# compute new ranges for i and j intervals and update labels on dialog
thisRng = val - thisMin + 1;
nextRng = nextMax - val;
thisRngLabel = dlgDistrib.GetCtrlByID( sprintf("labelRng%d", i) );
thisRngLabel.SetLabel( NumToStr(thisRng) );
nextRngLabel = dlgDistrib.GetCtrlByID( sprintf("labelRng%d", j) );
nextRngLabel.SetLabel( NumToStr(nextRng) );
# update counts and percentages
updateCounts(i, j);
thisCountLabel = dlgDistrib.GetCtrlByID( sprintf("labelCount%d", i) );
thisCountLabel.SetLabel( NumToStr(cellCount[i] ) );
nextCountLabel = dlgDistrib.GetCtrlByID( sprintf("labelCount%d", j) );
nextCountLabel.SetLabel( NumToStr(cellCount[j] ) );
thisPctLabel = dlgDistrib.GetCtrlByID( sprintf("labelPct%d", i) );
thisPctLabel.SetLabel( sprintf("%.2f", cellPct[i] ) );
nextPctLabel = dlgDistrib.GetCtrlByID( sprintf("labelPct%d", j) );
nextPctLabel.SetLabel( sprintf("%.2f", cellPct[j] ) );
} # end onChangeMax()
########################################################
### Callback procedure for OK button on main dialog.
### Set up intervals:
### find minimum and maximum values for each interval along with
### cell count and cell percentage percentage and store in arrays.
### Show information in Distribution dialog.
proc setUpIntervals ()
{
## get desired number of intervals from the dialog
numInterval = dlgmain.GetCtrlValueNum("numberIntervals");
printf("Number of intervals = %d \n", numInterval);
# resize the arrays to match the number of intervals requested
ResizeArrayClear(minRange, numInterval);
ResizeArrayClear(maxRange, numInterval);
ResizeArrayClear(cellCount, numInterval);
ResizeArrayClear(cellPct, numInterval);
# get distribution type from dialog
distribType = dlgmain.GetCtrlValueNum("distCombo");
#################################
### set up equal-range intervals
if (distribType == 0)
{
local numeric intervalWidth; # numeric range of interval in equal interval process
intervalWidth = ( globalRange ) / numInterval;
printf("interval width = %.1f\n", intervalWidth);
minRange[1] = minRast; # set minimum value for first interval
maxRange[numInterval] = maxRast; # set maximum value for last interval
## iterate through remaining intervals and set remaining min and max values
for i = 1 to (numInterval - 1)
{
## set max value for this interval; rounding ensures that no integer interval width is
## more than 1 value away from the target interval width
maxRange[i] = round( minRast - 1 + ( i * intervalWidth ) );
minRange[i + 1] = maxRange[i] + 1; # set minimum value for next interval
}
## use user-defined procedure to loop through input raster to get cell count and percentage for each interval
updateCounts(1, numInterval);
}
####################################
### set up equal-count intervals
else if (distribType == 1)
{
local numeric targetCount = 0; # number of cell counts per interval in equal-count
local numeric targetCount1; # current target count (offset from targetCount by remainder of previous interval)
local numeric rem; # difference between final interval count and current target count
globalNumCells = 0;
array numeric histo[globalRange]; # array for cell value histogram
# populate histogram array for raster and count number of non-null cells
for each RastIn
{
++ histo[RastIn - minRast + 1];
++ globalNumCells;
}
## compute target count per interval
targetCount = round( globalNumCells / numInterval );
printf("globalNumCells = %d, targetCount = %d \n", globalNumCells, targetCount);
targetCount1 = targetCount;
minRange[1] = minRast;
maxRange[numInterval] = maxRast;
j = 1; # initialize index to histogram array
## iterate through all but last interval and set remaining min and max values
for i = 1 to numInterval - 1
{
counter = 0;
while ( counter <= targetCount1 && j <= globalRange )
{
counter += histo[j];
# printf("i = %d, j = %d, cellCount = %d \n", i, j, counter);
++j;
}
if ( targetCount1 < (counter - ( histo[j-1] / 2 ) ) ) # target count reached before midpoint of last cell value
{
--j; # decrement histogram index to last interval added
cellCount[i] = counter - histo[j]; # omit last value from current interval
rem = targetCount1 - cellCount[i]; # shortfall relative to current target
targetCount1 = targetCount + rem; # increase target count for next interval by difference
} # between actual and target count
else
{
cellCount[i] = counter; # keep last value in current interval
rem = cellCount[i] - targetCount1; # remainder relative to current target count
targetCount1 = targetCount - rem; # decrease target count for next interval by difference
} # between actual and target count
maxRange[i] = (j - 1) + minRast - 1;
cellPct[i] = 100 * cellCount[i] / globalNumCells;
minRange[i+1] = maxRange[i] + 1; # set minimum value for next range
}
# count cells in last interval
counter = 0;
for i = j to globalRange
{
counter += histo[i];
# printf("i = %d, count = %d \n", i, counter);
}
cellCount[numInterval] = counter;
cellPct[numInterval] = 100 * counter / globalNumCells;
}
# string variable with skeleton of XML specification of the
# Distribution dialog window; controls and labels for the data
# for each interval will be added to the XML structure before the
# dialog is actually created.
xmldistrib$ = '<?xml version="1.0"?>
<root>
<dialog id="distribDlg" Title="Distribution" Buttons="" OnOpen="onOpenDistrib()">
<groupbox Name=" Global Values: " ExtraBorder="4">
<pane Orientation="horizontal">
<label>Minimum:</label>
<label id="globalMin"></label>
<label>Maximum:</label>
<label id="globalMax"></label>
<label>Range:</label>
<label id="globalRange"></label>
</pane>
</groupbox>
<pane Orientation="horizontal" HorizResize="Fixed">
<label>Distribution Type: </label>
<label id="distType"></label>
</pane>
<groupbox Extraborder="5">
<pane id="distribList" Orientation="vertical">
<pane Orientation="horizontal">
<label WidthGroup="1" HorizAlign="Center" TextAlign="Center">Minimum</label>
<label WidthGroup="2" HorizAlign="Center" TextAlign="Center">Maximum</label>
<label WidthGroup="3" HorizAlign="Center" TextAlign="Center">Range</label>
<label WidthGroup="4" HorizAlign="Center" TextAlign="Center">Count</label>
<label WidthGroup="5" HorizAlign="Center" TextAlign="Center">Percent</label>
<label WidthGroup="6" HorizAlign="Center" TextAlign="Center">Color</label>
</pane>
</pane>
</groupbox>
<pane Orientation="horizontal" HorizResize="fixed" HorizAlign="right">
<pushbutton Name=" Preview result... " OnPressed="onPreview()" HorizResize="Fixed" HorizAlign="Left"/>
<pushbutton Name=" OK " OnPressed="onOKdistrib()"/>
<pushbutton Name=" Cancel " OnPressed="onCancelDistrib()"/>
</pane>
</dialog>
</root>';
### Parse XML text for dialog into memory; return error if there are syntax errors.
errXML = docdistrib.Parse(xmldistrib$);
if ( errXML < 0 ) {
PopupError( errXML ); # pop up an error dialog
Exit( );
}
################################################################
### Modify the XML structure in memory before opening the dialog
### get XML nodes for global value labels
class XMLNODE minLabel, maxLabel, rngLabel;
minLabel = docdistrib.GetElementByID("globalMin");
maxLabel = docdistrib.GetElementByID("globalMax");
rngLabel = docdistrib.GetElementByID("globalRange");
### set global value labels
minLabel.SetText(sprintf("%d", minRast));
maxLabel.SetText(sprintf("%d", maxRast));
rngLabel.SetText(sprintf("%d", globalRange));
### set the Distribution Type label
class XMLNODE distType; # class instance for label for Distribution type
distType = docdistrib.GetElementByID("distType");
if (distribType == 0) then
distType.SetText( sprintf("Equal Range (%.1f)", intervalWidth) );
else
distType.SetText( sprintf("Equal Count (%d)", targetCount) );
### get the id for the pane that will contain a pane of controls for each interval
local class XMLNODE distribList;
distribList = docdistrib.GetElementByID("distribList");
# add horizontal pane and controls for each raster interval
local class XMLNODE paneRI; # reuseable class instance for new pane
local class XMLNODE editMin, editMax; # reuseable class instances for new editnumber field
local class XMLNODE labelRng, labelCount, labelPct; # reuseable class instances for labels for range, count, percentage
local class XMLNODE colorbut; # reuseable class instance for color button for row
local string interval$;
for i = 1 to numInterval
{
local string interval$ = NumToStr(i);
# printf("interval = %d, minRange = %d, maxRange = %d, range = %d, count = %d, cellPct = %.2f \n", i, minRange[i], maxRange[i], maxRange[i] - minRange[i] + 1, cellCount[i], cellPct[i]);
# add horizontal pane to hold controls
paneRI = distribList.NewChild( "pane");
paneRI.SetAttribute("Orientation", "horizontal");
# add editnumber control for minRange
editMin = paneRI.NewChild("editnumber");
editMin.SetAttribute("id", sprintf("editMin%s", interval$));
editMin.SetAttribute("Width", "6");
editMin.SetAttribute("MinVal", NumToStr(minRast));
editMin.SetAttribute("MaxVal", NumToStr(maxRast));
editMin.SetAttribute("Default", NumToStr(minRange[i]));
editMin.SetAttribute("WidthGroup", "1");
editMin.SetAttribute("HorizAlign", "Center");
editMin.SetAttribute("Precision", "0");
editMin.SetAttribute("OnChanged", sprintf("onChangeMin(this, %s)", interval$ ));
if (i == 1) then
editMin.SetAttribute("ReadOnly", "true");
else
editMin.SetAttribute("ReadOnly", "false");
# add editnumber control for maxRange
editMax = paneRI.NewChild("editnumber");
editMax.SetAttribute("id", sprintf("editMax%s", interval$));
editMax.SetAttribute("Width", "6");
editMax.SetAttribute("MinVal", NumToStr(minRast));
editMax.SetAttribute("MaxVal", NumToStr(maxRast));
editMax.SetAttribute("Default", NumToStr(maxRange[i]));
editMax.SetAttribute("WidthGroup", "2");
editMin.SetAttribute("HorizAlign", "Center");
editMax.SetAttribute("Precision", "0");
editMax.SetAttribute("OnChanged", sprintf("onChangeMax(this, %s)", interval$ ));
if (i == numInterval) then
editMax.SetAttribute("ReadOnly", "true");
else
editMax.SetAttribute("ReadOnly", "false");
# add label for range
labelRng = paneRI.NewChild("label");
labelRng.SetText(NumToStr(maxRange[i] - minRange[i] + 1));
labelRng.SetAttribute("id", sprintf("labelRng%s", interval$));
labelRng.SetAttribute("HorizAlign", "Center");
labelRng.SetAttribute("TextAlign", "Right");
labelRng.SetAttribute("WidthGroup", "3");
# add label for count
labelCount = paneRI.NewChild("label");
labelCount.SetText( NumToStr(cellCount[i] ) );
labelCount.SetAttribute("id", sprintf("labelCount%s", interval$));
labelCount.SetAttribute("TextAlign", "Right");
labelCount.SetAttribute("HorizAlign", "Center");
labelCount.SetAttribute("WidthGroup", "4");
# add label for percent
labelPct = paneRI.NewChild("label");
labelPct.SetText(sprintf("%.2f", cellPct[i]));
labelPct.SetAttribute("id", sprintf("labelPct%s", interval$));
labelPct.SetAttribute("WidthGroup", "5");
labelPct.SetAttribute("TextAlign", "Right");
labelPct.SetAttribute("HorizAlign", "Center");
# add color button
colorbut = paneRI.NewChild("colorbutton");
colorbut.SetAttribute("id", sprintf("colorbut%s", interval$));
colorbut.SetAttribute("WidthGroup", "6");
colorbut.SetAttribute("HorizAlign", "Center");
}
### Get the dialog element from the parsed XML text and show error message if
### the dialog element can't be found
nodedistrib = docdistrib.GetElementByID("distribDlg");
if (nodedistrib == 0)
{
PopupMessage("Could not find dialog node in XML document");
Exit();
}
### Set the XMl dialog element as the source for the GUI_DLG class instance we
### are using for the Distribution dialog window
dlgDistrib.SetXMLNode(nodedistrib);
### Open the dialog window as a modal dialog
dlgDistrib.DoModal();
} # end setUpIntervals()
#####################################################################
######################### Main program ##############################
#####################################################################
clear();
##############################################################
### Standard colors for initial color palette.
### Can be modified using color buttons in Distribution dialog.
xmlPalette$ = '<?xml version="1.0"?>
<palette name="Raster Interval Palette">
<color id="1" red="0" green="0" blue="100"/>
<color id="2" red="0" green="100" blue="0"/>
<color id="3" red="100" green="0" blue="0"/>
<color id="4" red="0" green="100" blue="100"/>
<color id="5" red="100" green="0" blue="100"/>
<color id="6" red="100" green="100" blue="0"/>
<color id="7" red="0" green="0" blue="72"/>
<color id="8" red="0" green="100" blue="72"/>
<color id="9" red="0" green="25" blue="0"/>
<color id="10" red="0" green="72" blue="100"/>
<color id="11" red="0" green="44" blue="44"/>
<color id="12" red="100" green="72" blue="72"/>
<color id="13" red="72" green="0" blue="0"/>
<color id="14" red="72" green="0" blue="100"/>
<color id="15" red="44" green="0" blue="0"/>
<color id="16" red="72" green="100" blue="72"/>
<color id="17" red="72" green="72" blue="0"/>
<color id="18" red="100" green="100" blue="67"/>
<color id="19" red="0" green="72" blue="0"/>
<color id="20" red="0" green="0" blue="44"/>
</palette>';
### parse XML text for color palette into memory; returns error code (number < 0)
### if there are syntax errors
errXML = docColor.Parse(xmlPalette$);
if ( errXML < 0 ) {
PopupError( errXML ); # pop up an error dialog
Exit( );
}
#################################################
### Set up main dialog window
### Create string variable with XML specification of main
### dialog enclosed in single quotes (for multiline text)
xmlmain$ = '<?xml version="1.0"?>
<root>
<dialog id="dlgmain" Title="Raster Intervals" Buttons="" OnOpen="onOpenMain()">
<groupbox ExtraBorder="3">
<label>Select a grayscale integer raster for the input raster:</label>
<pane Orientation="horizontal">
<pushbutton Name="Input Raster..." OnPressed="getRastIn()"/>
<edittext id="inRastText" width="40" ReadOnly="True"/>
</pane>
<pane Orientation="horizontal" HorizAlign="Left" HorizResize="Fixed">
<label>Number of intervals (maximum 20):</label>
<editnumber id="numberIntervals" Default="5" MinVal="2" MaxVal="30" Precision="0" Width="2"/>
<label>Distribution:</label>
<combobox id="distCombo" Default="0">
<item Value="0">Equal Range</item>
<item Value="1">Equal Count</item>
</combobox>
</pane>
</groupbox>
<pane Orientation="horizontal" HorizResize="Fixed" HorizAlign="Right">
<pushbutton id="runButton" Name="Run..." Enabled="false" OnPressed="setUpIntervals()"/>
<pushbutton Name="Exit" OnPressed="onExit()"/>
</pane>
</dialog>
</root>';
### parse XML text for main dialog into memory; returns error code (number < 0)
### if there are syntax errors
errXML = docmain.Parse(xmlmain$);
if ( errXML < 0 ) {
PopupError( errXML ); # pop up an error dialog
Exit( );
}
### get the dialog element from the parsed XML text and show error
### message if the dialog element can't be found
nodemain = docmain.GetElementByID( "dlgmain" );
if ( nodemain == 0 ) {
PopupMessage( "Could not find main dialog node in XML document" );
Exit();
}
### set the XML dialog element as the source for the GUI_DLG class instance
### we are using for the main dialog window
dlgmain.SetXMLNode(nodemain);
dlgmain.DoModal();