Syntax Highlighing:
comments, key words, predefined symbols, class members & methods, functions & classes
# TransferGeoref.sml
# Script to automate copying of georeference from original
# raster objects in TNT Project Files to rasters of the
# same dimensions that have been enhanced outside TNTmips
# and reimported.
# Assumptions:
# 1) Each georeferenced source and ungeoreferenced target consist of
# a single raster object in a Project File.
# 2) Source and target files are in different directories but have the
# same filenames.
# 3) The source raster object name is the same as its filename root. No
# restriction is placed on the name of the target raster object.
# The script processes all files with matching names in the selected
# source and target directories. A log file is created in the source
# directory to list successful result for each file or any errors.
# Potential errors reported in the custom dialog window and log file:
# 1) missing target files listed as "No Match" to source file
# 2) source raster could not be opened (object name and file name don't match)
# 3) source raster not georeferenced
# 4) target raster could not be opened
# Version 4 February 2011
# Modified to handle variable names for the target raster.
# Randy Smith, MicroImages, Inc.
############### Global Variables #################
class STRING sourceDir$, targetDir$;
class STRING logfilename$; # name of log file
class FILE logfile;
class STRINGLIST sourceList, targetList, confirmedTargetList;
class GUI_DLG dlgwin;
class GUI_CTRL_PUSHBUTTON targetDirBtn;
class GUI_CTRL_EDIT_STRING sourceDirText, targetDirText;
class GUI_CTRL_LISTBOX sourceListbox, targetListbox, procListbox;
class GUI_CTRL_EDIT_NUMBER numSource, numTarget, numProc;
class GUI_CTRL_EDIT_STRING statustext;
class GUI_CTRL_PUSHBUTTON runBtn, cancelBtn, closeBtn;
numeric err;
class STATUSDIALOG statusD;
class STATUSCONTEXT statusC;
##############################################
### function to find target Project File with same name as source
### and return its path string
func findTargetFile(class STRINGLIST list, class STRING name$)
{
local numeric i;
local numeric found = 0;
for i = 1 to list.GetNumItems()
{
if (list[i - 1] == name$) then
found = 1;
}
return found;
}
############################
### procedure to get the directory containing source maps with georeference
proc GetSourceDirectory()
{
local numeric i;
local numeric filecount;
sourceDir$ = GetDirectory("", "Select directory with source map files:");
class FILEPATH sourceDirPath(sourceDir$);
sourceDirText.SetValueStr(sourceDir$); # write source directory name to dialog
# clear dialog listboxes if they are still populated from a previous run
if (sourceListbox.GetCount() > 0) then
sourceListbox.DeleteAllItems();
if (targetListbox.GetCount() > 0) then
targetListbox.DeleteAllItems();
if (procListbox.GetCount() > 0)
{
procListbox.DeleteAllItems();
numProc.SetValueNum(0);
}
# clear stringlist containing matching filenames from previous run
if (confirmedTargetList.GetNumItems() > 0) then
confirmedTargetList.Clear();
targetDir$ = "";
targetDirText.SetValueStr(""); # clear target directory text field
statustext.SetValueStr(""); # clear status message text field
# get stringlist with names of Project Files in the source directory
sourceList = sourceDirPath.GetFileList("*.rvc");
sourceList.Sort();
# loop through stringlist to add names to the source listbox in the dialog
for i = 1 to sourceList.GetNumItems()
{
sourceListbox.AddItem( sourceList[i-1] );
}
# write number of source map files found to the editnumber in the dialog
numSource.SetValueNum(sourceList.GetNumItems() );
# enable Target Directory button and Cancel button
targetDirBtn.SetEnabled(1);
cancelBtn.SetEnabled(1);
# open log file for this run
logfilename$ = sprintf("%s/%s.log", sourceDir$, sourceDirPath.GetNameOnly() );
printf("Log file is %s\n", logfilename$);
logfile = fopen(logfilename$, "w");
fprint(logfile, "Log for script transferring map georeference (TransferGeoref.sml.");
fprintf(logfile, "Source directory = %s\n", sourceDir$);
fprintf(logfile, "Number of source maps found = %d\n", sourceList.GetNumItems() );
}
############################
### procedure to get the directory containing the target maps
proc GetTargetDirectory()
{
local numeric i;
local class STRING sourceName$, targetName$;
local numeric numFound = 0;
targetDir$ = GetDirectory("", "Select directory with target map files:");
class FILEPATH targetDirPath(targetDir$);
targetDirText.SetValueStr(targetDir$);
# get stringlist with names of Project Files in the target directory
targetList = targetDirPath.GetFileList("*.rvc");
# clear target listbox and target stringlist if necessary
if (targetListbox.GetCount() > 0) then
targetListbox.DeleteAllItems();
if (confirmedTargetList.GetNumItems() > 0) then
confirmedTargetList.Clear();
# loop through source filename stringlist to identify matching files in
# target directory and add them to the target listbox and add name to
# the confirmed target stringlist
for i = 1 to sourceList.GetNumItems()
{
sourceName$ = sourceList[i - 1];
if ( findTargetFile(targetList, sourceName$) == 1)
{
targetName$ = sourceName$;
++ numFound;
}
else
targetName$ = "No Match";
# add filename or "No Match" to confirmed list and to listbox
confirmedTargetList.AddToEnd(targetName$);
targetListbox.AddItem(targetName$);
}
# write number of target map files found to the editnumber in the dialog
numTarget.SetValueNum(numFound);
# enable Run button
runBtn.SetEnabled(1);
fprintf(logfile, "Target directory = %s\n", targetDir$);
fprintf(logfile, "Number of matching target map files found = %d\n", numFound);
}
############################
### procedure called by the Close button
proc onClose()
{
fclose(logfile);
dlgwin.Close(0);
Exit();
}
############################
### procedure called by the Cancel button
proc onCancel()
{
fclose(logfile);
dlgwin.Close(0);
Exit();
}
############################
### procedure called by the Run button
proc onRun()
{
local numeric i;
class RVC_RASTER SourceRast, TargetRast;
class RVC_OBJITEM sourceObjItem, targetObjItem;
local class STRING filename$; # name of Project File
local class STRING objname$, objpath$;
local class STRING sourcePath$, targetPath$, obj;
local numeric transferCount = 0;
local class STRING procListStr;
local class STRING finalStatus$;
local class STRINGLIST objNameList;
statusD.Create();
statusC = statusD.CreateContext();
# loop through list of source files to transfer georeference
for i = 1 to confirmedTargetList.GetNumItems()
{
filename$ = confirmedTargetList[i - 1];
statusC.Message = sprintf("Processing map %d, %s", i, filename$);
# check string returned for "No Match", indicating there is no matching target file
if (filename$ == "No Match") then
procListStr = "No matching target file";
else # target file exists
{
# construct filepaths for source and target rasters from filename$
sourcePath$ = sourceDir$ + "/" + filename$;
targetPath$ = targetDir$ + "/" + filename$;
class FILEPATH sourceFilepath(sourcePath$);
class FILEPATH targetFilepath(targetPath$);
# construct object path for source raster
objname$ = GetToken(filename$, ".", 1);
objpath$ = objname$ + ".RASTER";
# set filepath and object path for source raster
sourceObjItem.SetFilePath(sourceFilepath);
sourceObjItem.SetObjectPath(objpath$);
# open the source raster for reading
err = SourceRast.Open(sourceObjItem, "Read");
if (err >= 0) # source raster was successfully opened, check georeference
{
# check that source raster has georeference
if ( GetLastUsedGeorefObject(SourceRast) == 0) then
procListStr = "Source has no georeference";
else # source raster is georeferenced, get target raster
{
# get name of raster object in target file and construct object path
objNameList = GetAllObjectNames(targetPath$, "RASTER");
objname$ = objNameList.GetString(0);
objpath$ = objname$ + ".RASTER";
# set filepath and object path for target raster
targetObjItem.SetFilePath(targetFilepath);
targetObjItem.SetObjectPath(objpath$);
# open the target raster for reading
err = TargetRast.Open(targetObjItem, "Write");
if (err >= 0) # target raster successfully opened
{
# check that source and target have the same dimensions
if (TargetRast.$Info.NumLins == SourceRast.$Info.NumLins &&
TargetRast.$Info.NumCols == SourceRast.$Info.NumCols)
{
CopySubobjects(SourceRast, TargetRast, "GEOREF");
TargetRast.Close();
++transferCount; # increment count of successful transfers
procListStr = "Transferred";
}
else # source and target don't have the same dimensions.
procListStr = "Target has wrong dimensions";
} # end target opened
else # target raster could not be opened.
procListStr = "Target could not be opened";
} # end get target raster
SourceRast.Close();
} # end source raster opened
else # source raster could not be opened
procListStr = "Source could not be opened";
} # end target file exists
procListbox.AddItem(procListStr);
printf("Map %d, %s, result = %s\n", i, filename$, procListStr);
fprintf(logfile, "Map %d, %s, result = %s\n", i, filename$, procListStr);
} # end loop through confirmedTargetList
numProc.SetValueNum(transferCount);
if (transferCount == sourceList.GetNumItems() ) then
finalStatus$ = "Processing complete, no errors.";
else
finalStatus$ = "Processing complete with errors.";
statusD.Destroy();
runBtn.SetEnabled(0);
cancelBtn.SetEnabled(0);
statustext.SetValueStr(finalStatus$);
} # end onRun()
##################################################
################# Main Program #####################
clear();
_context.AbortOnError = 0; # let script do its own error handling
class STRING xml$='<?xml version="1.0"?>
<!DOCTYPE root SYSTEM "smlforms.dtd">
<root>
<dialog id="dlgxtiff" Title="Transfer Georeference" Buttons="">
<pane Orientation="Horizontal" HorizResize="Fixed">
<pushbutton Name=" Source Directory " OnPressed="GetSourceDirectory()"/>
<edittext id="sourceDirText" width="45" ReadOnly="true"/>
</pane>
<pane Orientation="Horizontal" HorizResize="Fixed">
<pushbutton id="targetDirBtn" Name=" Target Directory " Enabled="false" OnPressed="GetTargetDirectory()"/>
<edittext id="targetDirText" Width="45" ReadOnly="true"/>
</pane>
<groupbox ExtraBorder="3">
<pane Orientation="Horizontal" HorizResize="Fixed">
<pane Orientation="Vertical" HorizResize="Fixed" VertResize="Fixed">
<listbox id="sourceListbox" Width="20"/>
<pane Orientation="Horizontal" HorizResize="Fixed">
<editnumber id="numSource" Width="2" Precision="0" BlankZero="true" ReadOnly="true"/>
<label> source maps </label>
</pane>
</pane>
<pane Orientation="Vertical" HorizResize="Fixed" VertResize="Fixed">
<listbox id="targetListbox" Width="20"/>
<pane Orientation="Horizontal" HorizResize="Fixed">
<editnumber id="numTarget" Width="2" Precision="0" BlankZero="true" ReadOnly="true"/>
<label> target maps </label>
</pane>
</pane>
<pane Orientation="Vertical" HorizResize="Fixed" VertResize="Fixed">
<listbox id="procListbox" Width="30"/>
<pane Orientation="Horizontal" HorizResize="Fixed">
<editnumber id="numProc" Width="2" Precision="0" BlankZero="true" ReadOnly="true"/>
<label> transferred</label>
</pane>
</pane>
</pane>
</groupbox>
<pane Orientation="Horizontal" HorizAlign="left">
<edittext id="statustext" Width="20" ReadOnly="true"/>
</pane>
<pane Orientation="Horizontal" HorizAlign="right">
<pushbutton id="runBtn" Name=" Run " Enabled="false" OnPressed="onRun()"/>
<pushbutton id="cancelBtn" Name=" Cancel " Enabled="false" OnPressed="onCancel()"/>
<pushbutton id="closeBtn" Name=" Close " OnPressed="onClose()"/>
</pane>
</dialog>
</root>';
### parse XML text for the dialog into memory
class XMLDOC dlgdoc;
err = dlgdoc.Parse(xml$);
### get the dialog element from the parsed XML document
class XMLNODE dlgnode;
dlgnode = dlgdoc.GetElementByID("dlgxtiff");
### set the dialog XML element as the source for the GUI_DLG class instance
dlgwin.SetXMLNode(dlgnode);
dlgwin.CreateModeless();
### get handles for dialog controls
sourceDirText = dlgwin.GetCtrlByID("sourceDirText");
targetDirBtn = dlgwin.GetCtrlByID("targetDirBtn");
targetDirText = dlgwin.GetCtrlByID("targetDirText");
sourceListbox = dlgwin.GetCtrlByID("sourceListbox");
targetListbox = dlgwin.GetCtrlByID("targetListbox");
procListbox = dlgwin.GetCtrlByID("procListbox");
numSource = dlgwin.GetCtrlByID("numSource");
numTarget = dlgwin.GetCtrlByID("numTarget");
numProc = dlgwin.GetCtrlByID("numProc");
statustext = dlgwin.GetCtrlByID("statustext");
runBtn = dlgwin.GetCtrlByID("runBtn");
cancelBtn = dlgwin.GetCtrlByID("cancelBtn");
closeBtn = dlgwin.GetCtrlByID("closeBtn");
# open the dialog
dlgwin.Open();
WaitForExit();