OBJECT.sml

  Download

More scripts: Scripts By Jack

Syntax Highlighing:

comments, key words, predefined symbols, class members & methods, functions & classes
            
# ------------------------------------------------------------
# OBJECT.sml
# ------------------------------------------------------------
# SET WARNING LEVEL:
  $warnings 3
# ------------------------------------------------------------
# COMPUTE-WATERSHED FUNCTION flag STRING ASSIGNMENT:
# See ComputeWatershed SML Function for More Complex Options.
  string computeW$ = "Ridge";
# ------------------------------------------------------------
# DEFINE STRING VARIABLES FOR POPUP FUNCTION PROMPTS:
  string p$,p1$,p2$,p3$,p4$,p5$,p6$;
# ------------------------------------------------------------
# DEFINE PROCEDURE writeTitle:
  proc writeTitle() begin
     printf("DRAFT OBJECT.sml:\n");
     printf("        VERSION: May 4, 2006\n");
     printf("        PURPOSE: PRODUCE SCENE-OBJECT ");
     printf("POLYGONS (SOPs).\n");
     printf("                 FROM AN INPUT IMAGE RASTER.\n");
     printf("        DETAILS: FAQs_by_Jack H");
     printf("         AUTHOR: Dr. Jack F. Paris\n");
     printf("   CONTACT INFO: [email protected] ");
     printf(" 303-775-1195\n");
     printf("    ALLOWED USE: ONLY NON-COMMERCIAL\n\n");
  end
# ------------------------------------------------------------
# CLEAR CONSOLE WINDOW & ALLOW USER TO REPOSITION IT:
  clear();
  p1$ = "CONSOLE-WINDOW ADJUSTMENT\n";
  p2$ = "* IF NECESSARY, REPOSITION the CONSOLE WINDOW.\n";
  p3$ = "* Then, CLICK the OK Button."; p$  = p1$ + p2$ + p3$;
  PopupMessage(p$);
# ------------------------------------------------------------
# DECLARE VARIABLES, RASTER OBJECTS, and VECTOR OBJECTS:
  class   DATABASE db; class DBTABLEINFO table;
  class   WATERSHED w;
  string  rObjFileName$,rFilePath$,rFile$,rObj$,rinObj$;
  string  fNameEP$,fNameW$,fNameSOP$,fNameDum$,desc$;
  string  fNameEP2$;
  string  epFile$,epObj$,vNameW$,vOptsW$,wFile$,wObj$;
  string  rtype$,eptype$,vtopo$,tname$,tdesc$,f1$,f2$;
  numeric err,rObj,epObj,linscale,colscale;
  numeric optEP;
  numeric floorRin,ceilRin,minEP,eLen,cPTLinD,fThin,aIPMin;
  numeric lin,col,nlins,ncols,linm1,linp1,colm1,colp1;
  numeric linbegin,linend,colbegin,colend,i;
  numeric hnRin,nvRin,minRin,maxRin,vR;
  numeric r1,r2,r3,r4,r6,r7,r8,r9;
  numeric s1,s2,s3,s4,s5,s6,s7,s8,s9,slope;
  numeric rflag,rg1,rg2,rg3,rg4,ravg,cIso;
  numeric gradx,grady,gradmag;
  numeric vEP,vEPold,aminEP,amaxEP,epLin,epFac;
  numeric delPar,delParMin,delParMax;
  numeric fqsum,cfq,cf10,cf20,cf30,cf40,cf50;
  numeric cf60,cf70,cf80,cf90,cfU;
  numeric maxEP,eLenp1;
  numeric aIPL,aIPR,aIPv,nodeS,nodeE;
  numeric numE,numEM,nvpolys,nvlins;
  numeric nL,pL,pR,medL,medR,medMin,medMax,medOff,medOff2;
  numeric maxmed,ccL,ccR;
  numeric ccMin,lenL,lenLMax,wObj;
  raster  Rin,R,EP,EP2,Dum; vector  WATERSHED,SOP;
# ------------------------------------------------------------
# DEFINE proc checkHisto(Band)
# PURPOSE: Ensures that Input Raster Has Unsampled Histogram.
  proc checkHisto (raster Band) begin
     local numeric sampleInt;
     sampleInt = HistogramGetSampleInterval(Band);
     if (sampleInt > 1) begin
        DeleteHistogram(Band); CreateHistogram(Band,0);
     end
     else if (sampleInt == -1) then	begin
        CreateHistogram(Band,0);
     end
  end
# ------------------------------------------------------------
# WRITE TITLE & AUTHOR INFORMATION:
  writeTitle();
# ------------------------------------------------------------
# GET AN INPUT RASTER, Rin:
  printf("GOOD CHOICES FOR Rin: Any Tasseled Cap Raster");
  printf(" or Any SRFI Raster\n\n");
  GetInputRaster(Rin); nlins = NumLins(Rin);
  minRin = GlobalMin(Rin); maxRin = GlobalMax(Rin);
  rFile$ = GetObjectFileName(Rin);
  rObj = GetObjectNumber(Rin);
  rinObj$ = GetObjectName(rFile$,rObj);
  ncols = NumCols(Rin); rtype$ = RastType(Rin);
  checkHisto(Rin); linscale = LinScale(Rin);
  colscale = ColScale(Rin); hnRin = HasNull(Rin);
  if (hnRin == 1) then nvRin = NullValue(Rin);
# ------------------------------------------------------------
# OPTION: CONTINUE WITH AN EXISTING EP RASTER
#     OR: CREATE A NEW EP RASTER:
  p1$ = "EP RASTER OPTION:\n";
  p2$ = "   1: CREATE a NEW EP Raster\n";
  p3$ = "   2: CONTINUE with an EXISTING EP Raster\n";
  p4$ = "OPTION ENTERED:";
  p$ = p1$ + p2$ + p3$ + p4$;
  optEP = PopupNum(p$,1,1,2,0);
# ------------------------------------------------------------
# DEFINE VARIOUS FILE & PATH STRINGS USED IN THIS SCRIPT:
  rObjFileName$ = GetObjectFileName(Rin);
  rFilePath$ = FileNameGetPath(rObjFileName$);
  fNameEP$ = rFilePath$ + "\EP.rvc";
  fNameDum$ = rFilePath$ + "\DUMMY.rvc";
  fNameW$  = rFilePath$ + "\WATERSHED.rvc";
  fNameSOP$ = rFilePath$ + "\SOP.rvc";
# ------------------------------------------------------------
# PRINT INFORMATION ABOUT RASTER Rin TO CONSOLE WINDOW:
  printf("INPUT RASTER, Rin, INFORMATION:\n");
  printf("      Raster Name: %s\n",rinObj$);
  printf("       Data Range: From ");
  printf("%6d to %5d\n",minRin,maxRin);
  printf("     Line Spacing: %5.2f m     ",linscale);
  printf("Column Spacing: %5.2f m\n\n",colscale);
# ------------------------------------------------------------
# INITIAL VALUES FOR USER-SPECIFIED CONTROL-PARAMETERS:
     floorRin = minRin;
     ceilRin  = maxRin;
     minEP    =      1;
     eLen     =      1;
     cPTLinD  =      0;
     fThin    =      0;
     aIPMin   =      1;
     medOff   =      0;
# ------------------------------------------------------------
# DEFINITIONS OF CONTROL PARAMETERS:
#    floorRin = LOWEST ALLOWED VALUE for RASTER Rin
#    ceilRin  = HIGHEST ALLOWED VALUE for RASTER Rin
#    minEP    = THE MINIMUM ALLOWED VALUE FOR RASTER EP
#    eLen     = THE NUMBER OF CELLS FOR INTERPOLATION
#    cPTLinD  = CUMULATIVE-PERCENTILE FOR LINE DELETION
#    fThin    = THE VECTOR-LINE THINNING PARAMETER
#    aIPMin   = SMALLEST ALLOWED AREA FOR ISLAND POLYGONS
#    medOff   = ADDED OFFSET FOR SOP MEDIAN VALUES
# ------------------------------------------------------------
# USER INPUTS FOR CONTROL PARAMETERS:
# floorRin:
  p1$ = "INPUT-RASTER FLOOR-VALUE:\n";
  p2$ = "     DEFAULT = MINIMUM VALUE OF RASTER Rin\n";
  p3$ = "     IF PURPOSE IS TO DEFINE VEG OBJECTS:\n";
  p4$ = "          THEN USE TC2 AS Rin AND\n";
  p5$ = "          CHANGE VALUE NEAR ZERO.\n";
  p6$ = "VALUE ENTERED:";
  p$ = p1$ + p2$ + p3$ + p4$ + p5$ + p6$;
  floorRin = PopupNum(p$,floorRin,minRin,maxRin,0);
# ceilRin:
  p1$ = "INPUT-RASTER CEILING-VALUE:\n";
  p2$ = "     DEFAULT = MAXIMUM VALUE OF RASTER Rin\n";
  p3$ = "     IF PURPOSE IS TO DEFINE VEG OBJECTS:\n";
  p4$ = "          THEN USE TC2 AS Rin AND\n";
  p5$ = "          CHANGE VALUE NEAR 2000.\n";
  p6$ = "VALUE ENTERED:"; 
  p$ = p1$ + p2$ + p3$ + p4$ + p5$ + p6$;
  ceilRin = PopupNum(p$,ceilRin,minRin,maxRin,0);
# minEP:
  p1$ = "MINIMUM ALLOWED EDGE-PROBABILITY VALUE:\n";
  p2$ = "     RANGE: 1 to 5000\n";
  p3$ = "VALUE ENTERED:"; p$ = p1$ + p2$ + p3$;
  minEP = PopupNum(p$,minEP,1,5000,0); maxEP = 10000;
# eLen:
  p1$ = "EXTRAPOLATION-LINE LENGTH:\n";
  p2$ = "     RANGE: 1 to 9\n";
  p3$ = "     LIMIT: MUST BE AN ODD INTEGER\n";
  p4$ = "      NOTE: ENTER 1 FOR NO EXTRAPOLATION.\n";
  p5$ = "   PURPOSE: SMOOTHING & INTERPOLATION\n";
  p6$ = "VALUE ENTERED:"; 
  p$  = p1$ + p2$ + p3$ + p4$ + p5$ +p6$;
  eLen = PopupNum(p$,eLen,1,9,0);
  if (eLen > 2) then begin
     eLen = 2 * int(eLen / 2) + 1;
  end
  eLenp1 = eLen + 1;
# cPTLinD:
  if (optEP == 1) then begin
     p1$ = "CUMULATIVE-PERCENTILE FOR LINE DELETION:\n";
     p2$ = "     RANGE: 0 to 100 (percent)\n";
     p3$ = "      NOTE: ENTER 0 FOR NO DELETION.\n";
     p3$ = "VALUE ENTERED:"; p$ = p1$ + p2$ + p3$;
     cPTLinD = PopupNum(p$,cPTLinD,0,100,0);
  end
  if (optEP == 2) then cPTLinD = 0;
# fThin:
  p1$ = "VECTOR-LINE THINNING-FACTOR:\n";
  p2$ = "     RANGE: 0.00 to 3.00\n";
  p3$ = "      NOTE: If < 0.2, NO THINNING.\n";
  p4$ = "VALUE ENTERED:"; p$ = p1$ + p2$ + p3$ + p4$;
  fThin = PopupNum(p$,fThin,0,3,2);
# aIPMin:
  p1$ = "MINIMUM ISLAND-POLYGON AREA:\n";
  p2$ = "     RANGE: 1 to 1 million sq. m.\n";
  p3$ = "VALUE ENTERED:"; p$ = p1$ + p2$ + p3$;
  aIPMin = PopupNum(p$,aIPMin,1,1000000,0);
# medOff:
  if (cPTLinD > 0) then begin
     if (optEP == 1) then begin
        p1$ = "OFFSET FOR SOP MEDIAN VALUES:\n";
        p2$ = "     RANGE: 0 to 10000\n";
        p3$ = "VALUE ENTERED:"; p$ = p1$ + p2$ + p3$;
        medOff = PopupNum(p$,medOff,0,10000,0);
     end
  end
# ------------------------------------------------------------
# PRINT USER-SELECTABLE PARAMETERS TO CONSOLE WINDOW:
  printf("USER-SELECTABLE CONTROL PARAMETER VALUES:\n");
  printf("   floorRin: %7d\n",floorRin);
  printf("    ceilRin: %7d\n",ceilRin);
  printf("      minEP: %7d\n",minEP);
  printf("       eLen: %7d (cells)\n",eLen);
  if (optEP == 1) then begin
     printf("    cPTLinD: %10.2f (percentile)\n",cPTLinD);
  end
  printf("      fThin: %10.2f\n",fThin);
  printf("     aIPMin: %7d (sq. m.)\n",aIPMin);
  if (cPTLinD > 0) then begin
     if (optEP == 1) then begin
        printf("     medOff: %7d\n",medOff);
     end
  end
  printf("\n");
# ------------------------------------------------------------
# CREATE TEMPORARY RASTER, R, WHICH IS A COPY OF Rin:
  CreateTempRaster(R,nlins,ncols,rtype$);
  if (hnRin == 1) then IgnoreNull(Rin);
  IgnoreNull(R);
  for each R begin
     vR = Rin; R = vR;
  end
  CopySubobjects(Rin,R,"GEOREF");
  if (hnRin == 1) then begin
     SetNull(Rin,nvRin); DeleteHistogram(Rin);
     CreateHistogram(Rin,0);
  end
  rFile$ = GetObjectFileName(R); rObj = GetObjectNumber(R);
  rObj$ = GetObjectName(rFile$,rObj);
# ------------------------------------------------------------
# SET RASTER R VALUE TO floorRin OR TO ceilRin:
  numE = 0;
  for each R begin
     vR = R;
     if (vR < floorRin) then begin
        R = floorRin; numE = numE + 1;
     end
     if (vR > ceilRin) then begin
        R = ceilRin; numE = numE + 1;
     end
  end
  DeleteHistogram(R); CreateHistogram(R,0);
  printf("NUMBER OF RASTER R PIXELS CHANGED: %d\n",numE);
# ------------------------------------------------------------
# CREATE A NEW EDGE-PROBABILITIES (EP) RASTER:
  desc$ = "Based on " + rinObj$; eptype$ = "16-bit unsigned";
  if (optEP == 2) then begin
     GetInputRaster(EP,nlins,ncols,eptype$);
     printf("SCRIPT CONTINUES WITH AN EXISTING EP RASTER.\n");
  end
  else begin
     CreateRaster(EP,fNameEP$,"EP",desc$,nlins,ncols,eptype$);
     printf("SCRIPT STARTS WITH A NEW EP RASTER.\n");
     CopySubobjects(R,EP,"GEOREF");
  end
  epFile$ = GetObjectFileName(EP);
  epObj = GetObjectNumber(EP); 
  epObj$ = GetObjectName(epFile$,epObj);  
  CreateRaster(Dum,fNameDum$,"Dum","",1,1,"8-bit unsigned");
  DeleteObject(fNameDum$,1); PackRVC(fNameDum$);
  CreateRaster(EP2,fNameDum$,"EP2","",nlins,ncols,eptype$);
  EP2 = minEP;
# ------------------------------------------------------------
# CREATE A NEW SCENE-OBJECT-POLYGONS (SOP) VECTOR:
  desc$ = "Scene-Object-Polygons";
  CreateVector(SOP,fNameSOP$,"SOP",desc$,"VectorToolkit");
# ------------------------------------------------------------
# SET UP ARRAYS & PARAMETERS FOR EDGE-PROBABILITY PROCESS:
  if (eLen == 1) then begin
     eLen = 2; eLenp1 = 3;
  end
  array numeric x[eLenp1]; array numeric y[eLenp1];
  linbegin = eLen + 1; colbegin = eLen + 1;
  linend = nlins - eLen; colend = ncols - eLen;
  for i=1 to eLen begin
     x[i] = i - 1;
  end
# ------------------------------------------------------------
# SOBEL STAR CONFIGURATION:  xx: MARKS RELATIVE POSITIONS
#    OF THE EXTENDED "STAR" CELLS USED TO EXTRAPOLATE TO
#    THE SOBEL 3 by 3 FILTER ELEMENTS.
#
#    THE SOBEL-STAR CONFIGURATION BELOW IS FOR eLen = 3.
#
#               xx          xx          xx
#
#                   xx      xx      xx
#
#                       r1  r2  r3
#
#               xx  xx  r4  cc  r6  xx  xx
#
#                       r7  r8  r9
#
#                   xx      xx      xx
#
#               xx          xx          xx
#
# ------------------------------------------------------------
# SCAN THE IMAGE TO FIND amaxEP:
  printf("SCANNING TO FIND THE MAXIMUM EP VALUE ... ");
  amaxEP = 0;
  for lin = linbegin to linend begin
     for col = colbegin to colend begin
        # ESTIMATE VALUE (BY EXTRAPOLATION) AT CELL r1:
        for i=1 to eLen y[i] = R[(lin-i),(col-i)];
        slope = LinearRegression(x,y,eLen,s1,r1);
        # ESTIMATE VALUE (BY EXTRAPOLATION) AT CELL r2:
        for i=1 to eLen y[i] = R[(lin-i),col];
        slope = LinearRegression(x,y,eLen,s2,r2);
        # ESTIMATE VALUE (BY EXTRAPOLATION) AT CELL r3:
        for i=1 to eLen y[i] = R[(lin-i),(col+i)];
        slope = LinearRegression(x,y,eLen,s3,r3);
        # ESTIMATE VALUE (BY EXTRAPOLATION) AT CELL r4:
        for i=1 to eLen y[i] = R[lin,(col-i)];
        slope = LinearRegression(x,y,eLen,s4,r4);
        # ESTIMATE VALUE (BY EXTRAPOLATION) AT CELL r6:
        for i=1 to eLen y[i] = R[lin,(col+i)];
        slope = LinearRegression(x,y,eLen,s6,r6);
        # ESTIMATE VALUE (BY EXTRAPOLATION) AT CELL r7:
        for i=1 to eLen y[i] = R[(lin+i),(col-i)];
        slope = LinearRegression(x,y,eLen,s7,r7);
        # ESTIMATE VALUE (BY EXTRAPOLATION) AT CELL r8:
        for i=1 to eLen y[i] = R[(lin+i),col];
        slope = LinearRegression(x,y,eLen,s8,r8);
        # ESTIMATE VALUE (BY EXTRAPOLATION) AT CELL r9:
        for i=1 to eLen y[i] = R[(lin+i),(col+i)];
        slope = LinearRegression(x,y,eLen,s9,r9);
        # gradx (Spacing-Corrected Sobel 3 by 3 ALGORITHM):
        gradx = r3 + 2*r6 + r9 - (r1 + 2*r4 + r7);
        gradx = gradx / (8 * colscale);
        # grady (Spacing-Corrected Sobel 3 by 3 ALGORITHM):
        grady = r7 + 2*r8 + r9 - (r1 + 2*r2 + r3);
        grady = grady / (8 * linscale);
        # vEP (Absolute Gradiant Vector Magnitude):
        vEP = sqrt(gradx*gradx + grady*grady);
        if (vEP > amaxEP) then amaxEP = vEP;
     end
  end
  printf("Done\n\n");
  epFac = maxEP / amaxEP;
  printf("RESULTS OF EP SCAN:\n");
  printf("   Before being scaled up by epFac:\n");
  printf("   aminEP = %7.2f   amaxEP = %10.2f\n",aminEP,amaxEP);
  printf("   epFac  = %7.2f\n\n",epFac);
# ------------------------------------------------------------
# PROCESS RASTER R TO PRODUCE EDGE-PROBABILITY (EP) VALUES:
  printf("PRODUCING FINAL VALUES FOR EP RASTER ... ");
  aminEP = 2^16; amaxEP = 0;
  for lin = linbegin to linend begin
     for col = colbegin to colend begin
        for i=1 to eLen y[i] = R[(lin-i),(col-i)];
        slope = LinearRegression(x,y,eLen,s1,r1);
        for i=1 to eLen y[i] = R[(lin-i),col];
        slope = LinearRegression(x,y,eLen,s2,r2);
        for i=1 to eLen y[i] = R[(lin-i),(col+i)];
        slope = LinearRegression(x,y,eLen,s3,r3);
        for i=1 to eLen y[i] = R[lin,(col-i)];
        slope = LinearRegression(x,y,eLen,s4,r4);
        for i=1 to eLen y[i] = R[lin,(col+i)];
        slope = LinearRegression(x,y,eLen,s6,r6);
        for i=1 to eLen y[i] = R[(lin+i),(col-i)];
        slope = LinearRegression(x,y,eLen,s7,r7);
        for i=1 to eLen y[i] = R[(lin+i),col];
        slope = LinearRegression(x,y,eLen,s8,r8);
        for i=1 to eLen y[i] = R[(lin+i),(col+i)];
        slope = LinearRegression(x,y,eLen,s9,r9);
        gradx = r3 + 2*r6 + r9 - (r1 + 2*r4 + r7);
        gradx = gradx / (8 * colscale);
        grady = r7 + 2*r8 + r9 - (r1 + 2*r2 + r3);
        grady = grady / (8 * linscale);
        gradmag = sqrt(gradx*gradx + grady*grady);
        vEP = ceil(epFac * gradmag);
        if (vEP < aminEP) then aminEP = vEP;
        if (vEP > amaxEP) then amaxEP = vEP;
        vEP = Bound(vEP,minEP,maxEP);
        if (optEP == 2) then begin
           vEPold = EP[lin,col];
           if (vEP > vEPold) then begin
              EP[lin,col] = vEP;
           end
        end
        else EP[lin,col] = vEP;
     end
  end
# ------------------------------------------------------------
# FIND AND REPLACE ISOLATED EP CELLS THAT HAVE VALUES = minEP.
# REPLACEMENT VALUE IS THE MAXIMUM OF THE FOUR AVERAGES
# OF OPPOSING CELLS (HORIZONTAL, VERTICAL & THE TWO DIAGONALS):
  cIso = 0;
  for lin = linbegin to linend begin
     for col = colbegin to colend begin
        vEP = EP[lin,col];
        if (vEP == minEP) then begin
           rflag = 0; rg1 = 0; rg2 = 0; rg3 = 0; rg4 = 0;
           linm1 = lin - 1; linp1 = lin + 1;
           colm1 = col - 1; colp1 = colp1;
           r1 = EP[linm1,colm1];
           r9 = EP[linp1,colp1];
           if (r1 > minEP and r9 > minEP) then begin
              rflag = 1; rg1 = (r1 + r9) / 2;
           end
           r2 = EP[linm1,col];
           r8 = EP[linp1,col];
           if (r2 > minEP and r8 > minEP) then begin
              rflag = 1; rg2 = (r2 + r8) / 2;
           end
           r3 = EP[linm1,colp1];
           r7 = EP[linp1,colm1];
           if (r3 > minEP and r7 > minEP) then begin
              rflag = 1; rg3 = (r3 + r7) / 2;
           end
           r4 = EP[lin,colm1];
           r6 = EP[lin,colp1];
           if (r4 > minEP and r6 > minEP) then begin
              rflag = 1; rg4 = (r4 + r6) / 2;
           end
           if (rflag == 1) then begin
              ravg = SetMax(rg1,rg2,rg3,rg4);
              EP[lin,col] = ceil(ravg);
              cIso = cIso + 1;
           end
        end
     end
  end
  if (eLen == 2) then eLen = 1;
  for lin = linbegin to linend begin
     for col = colbegin to colend begin
        EP2[lin,col] = FocalMax(EP,eLen,eLen,lin,col,1);
     end
  end
# TRANSFER FILTERED EP2 VALUES TO EP RASTER:
  EP = EP2;
  printf("Done\n");
  printf("RASTER EP INFORMATION:\n");
  printf("   EP RANGE: From %4d to %7d\n",minEP,maxEP); 
  printf("   Isolated EP Cells (Changed): %d\n\n",cIso);
  IgnoreNull(EP); DeleteHistogram(EP); CreateHistogram(EP,0);
# ------------------------------------------------------------
# ASSIGN HANDLE (w) to EP RASTER:
# NOTE: EP is treated as a "DEM" so that the TNTmips
#       WATERSHED processes can be used to produce
#       Scene-Object Polygons (i.e., "WATERSHEDS").
  w = WatershedInit(epFile$,epObj$);
# ------------------------------------------------------------
# PROCESS RASTER EP TO MAKE SCENE-OBJECT POLYGONS (SOPs):
  printf("PROCESSING RASTER EP TO PRODUCE POLYGONS:\n");
  printf("   Making Scene-Object Polygons (SOPs) .... ");
  WatershedCompute(w,computeW$); printf("Done\n");
  printf("   Saving SOPs to WATERSHED Vector ........ ");
  WatershedGetObject(w,"VectorWatershed",wFile$,wObj$);
  wObj = ObjectNumber(wFile$,wObj$,"Vector");
  CopyObject(wFile$,wObj,fNameDum$);
  WatershedClose(w); CreateHistogram(EP,0);
  CreatePyramid(EP,0); CloseRaster(EP); 
  CloseRaster(EP2); printf("Done\n\n");
# ------------------------------------------------------------
# RE-OPEN VECTOR OBJECT, WATERSHED, FOR FURTHER PROCESSING:
  vNameW$ = "WATERSHED"; vOptsW$ = "VectorToolkit";
  OpenVector(WATERSHED,fNameDum$,vNameW$,vOptsW$);
  numEM = WATERSHED.$Info.NumPoints;
# ------------------------------------------------------------
# DELETE POUR POINTS FROM WATERSHED VECTOR OBJECT:
  array numeric ptlist[numEM + 1];
  for numE=1 to numEM begin
     ptlist[numE] = numE;
  end
  if (numEM > 0) then begin
     VectorDeletePoints(WATERSHED,ptlist,numEM);
  end
# ------------------------------------------------------------
# COPY WATERSHED VECTOR ELEMENTS TO VECTOR OBJECT SOP:
  nvlins = WATERSHED.$Info.NumLines;
  nvpolys = WATERSHED.$Info.NumPolys;
  VectorCopyElements(WATERSHED,SOP);
  CloseVector(WATERSHED);
# ------------------------------------------------------------
# DELETE LARGE POLYGON AROUND THE OUTSIDE EDGE OF RASTER EP:
  numeric polyNum, numPolyMaxArea, area, maxArea;
  for polyNum=1 to nvpolys begin
    area = SOP.poly[polyNum].POLYSTATS.Area;
    if (area > maxArea) begin
		maxArea = area;
		numPolyMaxArea = polyNum;
    end
  end
  if (SOP.Poly[numPolyMaxArea].Internal.MinX == 0 and SOP.Poly[numPolyMaxArea].Internal.MinY == 0) then
    VectorDeletePoly(SOP, numPolyMaxArea);
# ------------------------------------------------------------
# BUILD POLYGONS FROM MODIFIED LINES:
  printf("BUILDING INITIAL SOPs IN VECTOR SOP ....... ");
  VectorValidate(SOP);
  printf("Done\n");
# ------------------------------------------------------------
# MAKE A REPORT CONCERNING VECTOR SOP's ELEMENTS:
  nvpolys = SOP.$Info.NumPolys;
  nvlins = SOP.$Info.NumLines;
  printf("   Polygons: %d",nvpolys);
  printf("   Lines: %d\n\n",nvlins);
  printf("REMAINING PROCESSING STEPS");
  printf("                STATUS\n");
# ------------------------------------------------------------
# COMPUTE RASTER PROPERTIES (FROM R) FOR R_Props TABLE:
  tname$ = "R_Props"; tdesc$ = "R Attributes";
  f1$    = "Proportionally"; f2$    = "NULL";
  array numeric delLlist[nvlins];
# ------------------------------------------------------------
  if (optEP == 1) then begin
#    START PROCESS TO COMBINE & CLEAN UP SIMILAR SOPs:
     printf("   CREATING R_Props DATABASE TABLE ........ ");
     ComputeRasterProperties(Rin,SOP,tname$,tdesc$,f1$,f2$);
     printf("Done\n   ");
     if (cPTLinD > 0) then begin
#       PROCESS TO DELETE LINES BETWEEN SIMILAR SOPs:
#       DETERMINE RANGE OF DELETION PARAMETER (delPar):
        printf("DETERMINING RANGES ..................... ");
        medMin = 100000; medMax = -100000;
        for nL=1 to nvlins begin
           pL = SOP.line[nL].Internal.LeftPoly;
           pR = SOP.line[nL].Internal.RightPoly;
           if (pL > 0 and pR > 0) then begin
              ccL = SOP.poly[pL].R_Props.CellCount;
              ccR = SOP.poly[pR].R_Props.CellCount;
              ccMin = SetMin(ccL,ccR);
              if (ccMin > 5) then begin
                 medL = SOP.poly[pL].R_Props.Median;
                 medR = SOP.poly[pR].R_Props.Median;
                 if (medL < medMin) then medMin = medL;
                 if (medL > medMax) then medMax = medL;
                 if (medR < medMin) then medMin = medR;
                 if (medR > medMax) then medMax = medR;
              end
           end
        end
        medOff2 = medOff - medMin + 10;
        delParMin = 100000; delParMax = -100000;
        for nL = 1 to nvlins begin
           pL = SOP.line[nL].Internal.LeftPoly;
           pR = SOP.line[nL].Internal.RightPoly;
           if (pL > 0 and pR > 0) then begin
              ccL = SOP.poly[pL].R_Props.CellCount;
              ccR = SOP.poly[pR].R_Props.CellCount;
              ccMin = SetMin(ccL,ccR);
              if (ccMin > 5) then begin
                 medL = SOP.poly[pL].R_Props.Median;
                 medR = SOP.poly[pR].R_Props.Median;
                 medL = medL + medOff2; medR = medR + medOff2;
                 delPar = abs((medL - medR) / (medL + medR));
                 delPar = round(10000 * delPar);
                 if (delPar < delParMin) then delParMin = delPar;
                 if (delPar > delParMax) then delParMax = delPar;
              end
           end
        end
        printf("Done\n");
        printf("     Polygon Rin Median Range: %6d",medMin);
        printf(" to %6d\n",medMax);
        printf("     delPar             Range: %7d",delParMin);
        printf(" to %7d\n",delParMax);
#       CALCULATE CUMULATIVE DISTRIBUTION OF delPar VALUES:
        array numeric fq[delParMax + 1];
#       CALCULATE RAW FREQUENCY DISTRIBUTION (fq[i]):
        for nL = 1 to nvlins begin
           pL = SOP.line[nL].Internal.LeftPoly;
           pR = SOP.line[nL].Internal.RightPoly;
           if (pL > 0 and pR > 0) then begin
              ccL = SOP.poly[pL].R_Props.CellCount;
              ccR = SOP.poly[pR].R_Props.CellCount;
              ccMin = SetMin(ccL,ccR);
              if (ccMin > 5) then begin
                 medL = SOP.poly[pL].R_Props.Median;
                 medR = SOP.poly[pR].R_Props.Median;
                 medL = medL + medOff2; medR = medR + medOff2;
                 delPar = abs((medL - medR) / (medL + medR));
                 delPar = round(10000 * delPar);
                 fq[delPar] = fq[delPar] + 1;
              end
           end
        end
        fqsum = 0;
#       CALCULATE SUM OF RAW FREQUENCY VALUES:
        for i=0 to delParMax begin
           fqsum = fqsum + fq[i];
        end
#       CALCULATE CUMULATIVE FREQUENCY DISTRIBUTION:
        cfq = 0; cf10 = 0; cf20 = 0; cf30 = 0; cf40 = 0;
        cf50 = 0; cf60 = 0; cf70 = 0; cf80 = 0; cfU = 0;
        for i=0 to delParMax begin
           cfq = cfq + fq[i] / fqsum;
           fq[i] = 100 * cfq;
           if (cfU == 0) then begin
              if (fq[i] >= cPTLinD) then cfU = i;
           end
           if (cf10 == 0) then begin
              if (fq[i] >= 10) then cf10 = i;
           end
           if (cf20 == 0) then begin
              if (fq[i] >= 20) then cf20 = i;
           end
           if (cf30 == 0) then begin
              if (fq[i] >= 30) then cf30 = i;
           end
           if (cf40 == 0) then begin
              if (fq[i] >= 40) then cf40 = i;
           end
           if (cf50 == 0) then begin
              if (fq[i] >= 50) then cf50 = i;
           end
           if (cf60 == 0) then begin
              if (fq[i] >= 60) then cf60 = i;
           end
           if (cf70 == 0) then begin
              if (fq[i] >= 70) then cf70 = i;
           end
           if (cf80 == 0) then begin
              if (fq[i] >= 80) then cf80 = i;
           end
           if (cf90 == 0) then begin
              if (fq[i] >= 90) then cf90 = i;
           end
        end
#       PRINTOUT CUMULATIVE FREQUENCY DISTRIBUTION DATA:
        printf("     delPar at %4.1f Percentile:",cPTLinD);
        printf(" %d \n",cfU);
        printf("     CUMULATIVE DISTRIBUTION OF delPar:\n");
        printf("     cfq   delPar\n");
        printf("      10%9d\n",cf10);
        printf("      20%9d\n",cf20);
        printf("      30%9d\n",cf30);
        printf("      40%9d\n",cf40);
        printf("      50%9d\n",cf50);
        printf("      60%9d\n",cf60);
        printf("      70%9d\n",cf70);
        printf("      80%9d\n",cf80);
        printf("      90%9d\n",cf90);
#       BEGIN PROCESS TO DELETE WEAK POLYLINES:
        printf("   FINDING WEAK EDGES ..................... ");
        for nL=1 to nvlins begin
           delLlist[nL] = 0;
        end
        numEM = 0;
        for nL = 1 to nvlins begin
           pL = SOP.line[nL].Internal.LeftPoly;
           pR = SOP.line[nL].Internal.RightPoly;
           if (pL > 0 and pR > 0) then begin
              ccL = SOP.poly[pL].R_Props.CellCount;
              ccR = SOP.poly[pR].R_Props.CellCount;
              ccMin = SetMin(ccL,ccR);
              if (ccMin > 5) then begin
                 medL = SOP.poly[pL].R_Props.Median;
                 medR = SOP.poly[pR].R_Props.Median;
                 medL = medL + medOff2; medR = medR + medOff2;
                 delPar = abs((medL - medR) / (medL + medR));
                 delPar = round(10000 * delPar);
                 if (delPar < cfU) then begin
                    numEM = numEM + 1;
                    delLlist[numEM] = nL;
                 end
              end
           end
        end
        printf("Done\n   ");
        printf("COMBINING SOPs THAT ARE ALIKE .......... ");
        if (numEM > 0) then begin
           VectorDeleteLines(SOP,delLlist,numEM);
        end
        printf("Done\n   ");
#       (RE)BUILD SOPs:
        printf("(RE)BUILDING SOPs ...................... ");
        VectorValidate(SOP);
        printf("Done\n   ");
     end
#    BEGIN PROCESS TO DELETE DANGLING LINES:
     lenLMax = 0; nvlins = SOP.$Info.NumLines;
     for nL=1 to nvlins begin
        lenL = SOP.line[nL].LINESTATS.Length;
        if (lenL > lenLMax) then lenLMax = lenL;
     end
     lenLMax = lenLMax + 1;
     printf("DELETING DANGLING LINES IN SOP ......... ");
     VectorDeleteDangleLines(SOP,lenLMax);
     printf("Done\n   ");
#    RE-BUILD SOPs:
     printf("(RE)BUILDING SOPs ...................... ");
     VectorValidate(SOP);
     printf("Done\n");
  end
# ------------------------------------------------------------
# DELETE LINES ASSOCIATED WITH SMALL ISLAND POLYGONS in SOP:
  printf("   FINDING ISLAND-POLYGONS TO DELETE ...... ");
  nvlins = SOP.$Info.NumLines;
# RE-SET delLlist ARRAY VALUES TO ZERO: 
  for numE=1 to nvlins begin
     delLlist[numE] = 0;
  end
  numEM = 0;
# LINES ASSOCIATED WITH ISLAND POLYGONS USE SAME NODE NUMBER
# FOR START NODE AND ENDING NODE:
  for nL=1 to nvlins begin
     nodeS = SOP.line[nL].Internal.StartNode;
     nodeE = SOP.line[nL].Internal.EndNode;
#    FIND AREA OF SMALLER RELATED POLYGON:
     if (nodeS == nodeE) then begin
        pL = SOP.line[nL].Internal.LeftPoly;
        pR = SOP.line[nL].Internal.RightPoly;
        aIPL = SOP.poly[pL].POLYSTATS.Area;
        aIPR = SOP.poly[pR].POLYSTATS.Area;
        aIPv = SetMin(aIPL,aIPR);
#       TEST aIPv (AREA) AGAINST aIPMin:
        if (aIPv < aIPMin) then begin
           numEM = numEM + 1;
           delLlist[numEM] = nL;
        end
     end
  end
# END OF PROCESS TO DEFINE & DELETE WEAK EDGES
# ------------------------------------------------------------
  printf("Done\n   ");
# PERFORM THE LINE-DELETION PROCESS (FOR SMALL ISLANDS):
  if (numEM > 0) then begin
     printf("DELETING %5d ISLAND-POLYGONS ......... ",numEM);
     if (numEM > 0) then begin
        VectorDeleteLines(SOP,delLlist,numEM);
     end
     printf("Done\n   ");
     printf("(RE)BUILDING SOPs ...................... ");
     VectorValidate(SOP);
     printf("Done\n   ");     
  end
  if (numEM == 0) then begin
     printf("   No Island Polygons Were Deleted.\n   ");
  end
# ------------------------------------------------------------
  if (optEP == 1) then begin
#    DELETE TABLE NAMED R_Props:
     db = OpenVectorPolyDatabase(SOP);
     table = DatabaseGetTableInfo(db,tname$);
     printf("DELETING R_Props DATABASE TABLE ........ ");
     err = TableDelete(table);
     printf("Done\n   ");
  end
# IF optEP == 2, THEN SUBJECT TABLE DOES NOT EXIST.
# ------------------------------------------------------------
  if (fThin >= 0.2) then begin
#    RUN LINE THINNING PROCESS:
     printf("THINNING VECTOR SOP LINES .............. ");
     VectorThinLines(SOP,"Douglas-Peucker",fThin);
     printf("Done\n   ");
     VectorRemoveExcessNodes(SOP);
     printf("(RE)BUILDING SOPs ...................... ");
     VectorValidate(SOP);
     printf("Done\n   ");
  end
# ------------------------------------------------------------
# FINAL DELETION OF DANGLING LINES IN VECTOR SOP:
  lenLMax = 0; nvlins = SOP.$Info.NumLines;
  for nL=1 to nvlins begin
     lenL = SOP.line[nL].LINESTATS.Length;
     if (lenL > lenLMax) then lenLMax = lenL;
  end
  lenLMax = lenLMax + 1;
  printf("DELETING DANGLING LINES IN SOP ......... ");
  VectorDeleteDangleLines(SOP,lenLMax);
  printf("Done\n   ");
# ------------------------------------------------------------
# RE-SET Rin TO INPUT CONDITIONS & CLOSE IT:
  if (hnRin == 1) then begin
     SetNull(Rin,nvRin);
     DeleteHistogram(Rin); CreateHistogram(Rin,0);
  end
  CloseRaster(Rin);
# ------------------------------------------------------------
# BUILDING FINAL SOPs:
  printf("(RE)BUILDING FINAL SOPs ................ ");
  VectorValidate(SOP); 
  printf("Done\n\n");
# ------------------------------------------------------------
# MAKE REPORT OF VECTOR ELEMENTS IN FINAL SOP VECTOR OBJECT:
  nvlins = SOP.$Info.NumLines;
  nvpolys = SOP.$Info.NumPolys;
  printf("FINAL VECTOR SOPs & EDGE LINES:\n");
  printf("   Polygons: %d",nvpolys);
  printf("   Lines: %d\n\n",nvlins);
# ------------------------------------------------------------
# CLOSE VECTOR OBJECT SOP:
  CloseVector(SOP);
# ------------------------------------------------------------
# DELETE TEMPORARY RASTER R: 
  DeleteTempRaster(R);
# ------------------------------------------------------------
  printf("TO SAVE THE CONSOLE WINDOW TEXT AS A REPORT:\n");
  printf("   1. RIGHT-CLICK IN THE CONSOLE WINDOW.\n");
  printf("   2. SELECT THE Save As... OPTION.\n");
  printf("   3. NAVIGATE TO THE DESIRED LOCATION.\n");
  printf("   4. PROVIDE A REPORT NAME (or OVERWRITE).\n");
  printf("   5. CLICK OK.\n\n");
  printf("*** TO CONTINUE, YOU MUST EXIT SML EDITOR ***");
# ------------------------------------------------------------
# DELETE DUMMY.rvc FILE:
  DeleteFile(fNameDum$);