pihmRasterLIBS/flood.cpp

Go to the documentation of this file.
00001 /* flood.c  Program to implement flooding algorithm to assign flow directions and fill 
00002    pits/pools in a DEM.  Uses ESRI arcview format IO files.  Modified from
00003    setdir2.c 
00004   David G Tarboton
00005   Utah State University    
00006   
00007   SINMAP package version 0.1 9/2/97   */
00008 
00009 #include "lsm.h"
00010 #include "gridio.h"
00011 /*  This include declares all necessary global variables  */
00012 
00013 int addstack(int i, int j);
00014 
00015 /************************************************************************/
00016 int flood(char *demfile, char *pointfile, char *newfile)
00017 {
00018   int err;
00019 /*  float mval;
00020   double bndbox[4],csize;    These are external now */   
00021 
00022 /* define directions */
00023    d1[1]=0; d1[2]= -1; d1[3]= -1; d1[4]= -1; d1[5]=0; d1[6]=1; d1[7]=1; d1[8]=1;
00024    d2[1]=1; d2[2]=1; d2[3]=0; d2[4]= -1; d2[5]= -1; d2[6]= -1; d2[7]=0; d2[8]=1;
00025 
00026   err=gridread(demfile,(void ***)&elev,RPFLTDTYPE,&nx,&ny,&dx,&dy,bndbox,&csize,&mval,&filetype);
00027              
00028   if(err != 0)return(err);
00029 /*  allocate  dir and stack arrays  */
00030   dir = (short **) matalloc(nx, ny, RPSHRDTYPE);
00031   apool = (short **) matalloc(nx, ny, RPSHRDTYPE);
00032   istack = (int) (nx * ny * 0.1);
00033   pstack=istack;
00034   dn = (short *)malloc(sizeof(short) * istack);
00035   is = (short *)malloc(sizeof(short) * istack);
00036   js = (short *)malloc(sizeof(short) * istack);
00037   ipool = (short *)malloc(sizeof(short) * pstack);
00038   jpool = (short *)malloc(sizeof(short) * pstack);
00039   if(dn == NULL || is == NULL || js == NULL || ipool == NULL || jpool == NULL)
00040   {
00041      printf("\nError:  Cannot allocate memory for stacks\n");
00042      return(11);
00043   }
00044 /*  nmax=200;   Decided to elim iteration
00045   nnx=nx/nmax+1;
00046   nny=ny/nmax+1;
00047   while(nnx > 1 || nny > 1)
00048   {
00049     for(ix=0; ix<nnx; ix++)for(iy=0; iy<nny; iy++)
00050     {
00051       i1=ix*nmax;
00052       n1=i1+nmax;
00053       if(n1>nx)
00054       {
00055         n1=nx;
00056         i1=nx-nmax;
00057         if(i1<0)i1=0;
00058       }
00059       i2=iy*nmax;
00060       n2=i2+nmax;
00061       if(n2>ny)
00062       {
00063         n2=ny;
00064         i2=ny-nmax;
00065         if(i2<0)i2=0;
00066       }
00067       printf("Ranges: %d %d %d %d\n",i1,n1,i2,n2);
00068       setdf(mval);   /*  this call for range i1,n1,i2,n2  
00069     }
00070     nmax=(int) (nmax*3.5) ; 
00071     nnx=nx/nmax+1;
00072     nny=ny/nmax+1;
00073   }  /*  end of while  */
00074   i1=0; i2=0; n1=nx; n2=ny;  /*  full grid  */ 
00075   printf("Grid size: %d x %d\n",n1,n2);
00076   setdf(mval);
00077 /*  free stacks  */
00078   free(dn); free(is); free(js); free(ipool); free(jpool); 
00079   free(apool[0]); free(apool);
00080 /*    filetype=0;   0=ASCII   1= ARCVIEW proprietary  */
00081   printf("Writing output ...");
00082   err = gridwrite(newfile,(void **)elev,RPFLTDTYPE,nx,ny,dx,dy,
00083              bndbox,csize,mval,filetype);
00084   if(err != 0)return(err);
00085 /*  err = gridwrite(pointfile,(void **)dir,RPSHRDTYPE,nx,ny,dx,dy,
00086              bndbox,csize,-1,filetype);  
00087   if(err != 0)return(err);    */ 
00088   return(0);  /*  ALL OK return from flood  */
00089 }
00090 
00091 int setdf(float mval)
00092 {
00093   int i,j,k,n,nflat,ni,ip,imin,err,jn,in,np1,nt;
00094   float fact[9],per=1.;
00095 
00096 /*  Initialize boundaries  */
00097   for(i=i1; i< n1; i++)
00098   {
00099      dir[i][i2]= -1;
00100      dir[i][n2-1]= -1;
00101   }
00102   for(i=i2; i< n2; i++)
00103   {
00104      dir[i1][i]= -1;
00105      dir[n1-1][i]= -1;
00106   }
00107 /*  initialize internal pointers */
00108   for(i=i2+1; i< n2-1; i++)for(j=i1+1; j<n1-1; j++)
00109   {
00110     if(elev[j][i] <= mval)dir[j][i]= -1;
00111     else dir[j][i] = 0;
00112   }
00113 /*  Direction factors  */
00114   for(k=1; k<= 8; k++)
00115     fact[k]=(float)(1./sqrt(d1[k]*dy*d1[k]*dy+d2[k]*d2[k]*dx*dx));
00116 /*  printf("Problem Pixels \n");   */
00117 /*  printf("     Flats   Unresolved\n");  */   
00118 /*  Set positive slope directions - store unresolved on stack */
00119 /*ttt  n=1;      Avoid iterating - work with stack only
00120   while(n >= 1)
00121   {       */
00122   nis=0;
00123   for(i=i2+1; i< n2-1; i++)for(j=i1+1; j<n1-1; j++)
00124   {
00125     if(elev[j][i] > mval)set(i,j,fact,mval);
00126 /*  Put unresolved pixels on stack  */
00127     if(dir[j][i] == 0)
00128     {
00129                 err=addstack(i,j);
00130     }
00131    }
00132    nflat=nis;
00133 /* routine to drain flats to neighbors  */
00134    SetWorkingStatus();  
00135    imin=vdn(nflat);
00136    n=nis;
00137  
00138    printf("Number of pits to resolve: %d\n",n);  
00139    np1=n;
00140    nt=np1*(1-per/100);
00141 
00142 /*  initialize apool to zero  */
00143    for(i=i2; i< n2; i++)for(j=i1; j<n1; j++)
00144     apool[j][i]=0;
00145 /*  store unresolved stack location in apool for easy deletion  
00146   for(k=1; k<=nis; k++)
00147     apool[js[k]][is[k]]= - k;   */
00148 /*  pooln=0;  */
00149   while(nis > 0)   /*  While AA */
00150   {
00151 /*    fp=fopen("temp.dat","w");
00152         for(ip=1; ip <= nis; ip++)
00153         {
00154                 i=is[ip];
00155                 j=js[ip];
00156        fprintf(fp,"%d %d %f\n",i,j,elev[j][i]);
00157         }
00158     fclose(fp);   */
00159 
00160     i=is[imin];
00161     j=js[imin];
00162 /*      if(i == 12 && j == 27)
00163         {
00164                 printf("Here");
00165         }    */
00166 /*    pooln=pooln+1;  */
00167         pooln=1;
00168     npool=0;
00169     nf = 0;  /*  reset flag to that new min elev is found */
00170     pool(i,j);  /*  Recursive call on unresolved point with lowest elevation */
00171 /*  Find the pour point of the pool  */
00172 /*       err = gridwrite("pool.asc",(void **)apool,RPSHRDTYPE,nx,ny,dx,dy,
00173              bndbox,csize,-9999,0);   */ 
00174  
00175         for(ip=1; ip<=npool; ip++)
00176         {
00177                 i=ipool[ip];
00178                 j=jpool[ip];
00179                 for(k=1; k <=8; k++)    
00180         {
00181                          jn=j+d2[k];
00182                          in=i+d1[k];
00183                          if(apool[jn][in] != pooln)  /*  neighbor not in pool  */
00184                          {
00185                 et=max2(elev[j][i],elev[jn][in]);
00186                 if(nf == 0)  /*  this is the first edge found  */
00187                 {
00188                   emin=et;
00189                   nf=1;
00190 /*                                ipour=i;
00191                                   jpour=j;   */
00192                 }
00193                 else
00194                 {
00195                   /*  emin=min2(emin,et);  */
00196                                         if(emin > et)
00197                                         {
00198                                                 emin = et;
00199 /*                                              ipour=i;
00200                                                 jpour=j;    */
00201                                         }
00202                 }
00203                          }
00204                 }
00205         }
00206 /*  Fill the pool  */
00207     for(k=1; k<=npool; k++)
00208         {
00209                 i=ipool[k];
00210                 j=jpool[k];
00211       if(elev[j][i] <= emin)
00212           {
00213                   if(dir[j][i] > 0)   /*  Can be in pool, but not flat   */
00214                   {
00215                           dir[j][i]=0;
00216                           /*  Add to stack  */
00217                           err=addstack(i,j);
00218                   }
00219                   for(ip=1; ip <=8; ip++)
00220                   {
00221                           jn=j+d2[ip];
00222                           in=i+d1[ip];
00223                           if(elev[jn][in] > elev[j][i] && dir[jn][in] > 0)
00224 /*    Only zero direction of neighbors that are higher - because
00225       lower  or equal may be a pour point in a pit that must not be disrupted  */
00226                           {
00227                                   dir[jn][in] = 0;
00228                                   err=addstack(in,jn);
00229                           }
00230                   }
00231                   elev[j][i] =emin;
00232 
00233           }
00234           apool[j][i]=0;  /*  Reinitialize for next time round  */
00235         }
00236 
00237 /* reset unresolved stack  */
00238     ni=0;
00239     for(ip=1; ip <= nis; ip++)
00240     {
00241        set(is[ip],js[ip],fact,mval);  
00242            if(dir[js[ip]][is[ip]] == 0)  /* still on stack */
00243        {
00244           ni++;
00245           is[ni]=is[ip];
00246           js[ni]=js[ip];
00247 /*          apool[js[ni]][is[ni]] = -ni;  /*  Need to resave stack locations
00248                                          since the stack is being shortened */
00249        }
00250 /*         else
00251                    apool[js[ip]][is[ip]] = 0;   /*  Out of pool   */
00252      }
00253 /*    fp=fopen("temp.dat","w");
00254         for(ip=1; ip <= nis; ip++)
00255         {
00256                 i=is[ip];
00257                 j=js[ip];
00258        fprintf(fp,"%d %d %f\n",i,j,elev[j][i]);
00259         }
00260     fclose(fp);      */
00261 
00262          n=nis;
00263          imin=vdn(ni);
00264          if(nis < nt){
00265                  printf("Percentage done %f\n",per);
00266                  per=per+1;
00267                  nt=np1*(1-per/100);
00268          }
00269          /*  Debug writes   
00270      err = gridwrite("elev.asc",(void **)elev,RPFLTDTYPE,nx,ny,dx,dy,
00271              bndbox,csize,mval,0); 
00272          err = gridwrite("pool.asc",(void **)apool,RPSHRDTYPE,nx,ny,dx,dy,
00273              bndbox,csize,-9999,0);   */  
00274   }  /*  end of while AA  */
00275 
00276   return(err);
00277 }
00278 int vdn(int n)
00279 {
00280   int ip,k,imin;
00281   float ed;
00282   nis=n;
00283   do
00284   {
00285   n=nis;
00286   nis=0;
00287   for(ip=1; ip <=n; ip++)dn[ip]=0;
00288   for(k=1; k<=7; k=k+2)
00289     for(ip=1; ip<=n; ip++)
00290     {
00291        ed=elev[js[ip]][is[ip]]-elev[js[ip]+d2[k]][is[ip]+d1[k]];
00292        if(ed >= 0. && dir[js[ip]+d2[k]][is[ip]+d1[k]] != 0 && dn[ip] == 0)
00293          dn[ip]=k;
00294     }
00295   for(k=2; k<=8; k=k+2)
00296     for(ip=1; ip<=n; ip++)
00297     {
00298        ed=elev[js[ip]][is[ip]]-elev[js[ip]+d2[k]][is[ip]+d1[k]];
00299        if(ed >= 0. && dir[js[ip]+d2[k]][is[ip]+d1[k]] != 0 && dn[ip] == 0)
00300          dn[ip]=k;
00301     }
00302   imin=1;  /*  location of point on stack with lowest elevation  */
00303   for(ip=1; ip <= n; ip++)
00304   {
00305      if(dn[ip] > 0)dir[js[ip]][is[ip]]=dn[ip];
00306      else
00307      {
00308         nis++;
00309         is[nis]=is[ip];
00310         js[nis]=js[ip];
00311         if(elev[js[nis]][is[nis]] < elev[js[imin]][is[imin]])imin=nis;
00312      }
00313   }
00314   SetWorkingStatus(); 
00315   }while(nis < n);
00316   return(imin);
00317 }   
00318 
00319 void set(int i,int j,float *fact,float mval)
00320 {
00321   float slope,smax;
00322   int k;
00323   dir[j][i]=0;  /* This necessary for repeat passes after level raised */
00324   smax=0.;
00325   for(k=1; k<=8; k++)
00326   {
00327     if(elev[j+d2[k]][i+d1[k]] <= mval) dir[j][i] = -1;
00328     slope=fact[k]*(elev[j][i]-elev[j+d2[k]][i+d1[k]]);
00329     if(slope > smax && dir[j][i] != -1)
00330     {
00331        smax=slope;
00332        dir[j][i]=k;
00333     }
00334   }
00335 }
00336 /* function to compute pool recursively and at the same time determine
00337    the minimum elevation of the edge. */
00338 int pool(int i,int j)
00339 
00340   {
00341     int in,jn,k;
00342     if(apool[j][i]<=0)   /* not already part of a pool  */
00343     {
00344 /*      if(i!=0 && i!=ny-1 && j!=0 && j!=nx-1 && dir[j][i]!= -1)  */
00345         if(dir[j][i]!= -1)  /* check only dir since dir was initialized  */
00346                  /* not on boundary  */
00347       {
00348         apool[j][i]=pooln;  /*  apool assigned pool number */
00349         npool=npool+1;
00350         if(npool >= pstack)
00351         {
00352           if(pstack < (nx*ny))
00353           {
00354 /*  Try enlarging   */
00355             printf("\n Enlarging pool stack\n");
00356             pstack=(int) (pstack + nx*ny*.1);
00357             if(pstack > nx*ny)
00358             {
00359               printf("\n Pool stack too large, exiting ...\n");
00360               return(14);
00361             }
00362             ipool = (short *)realloc(ipool, sizeof(short) * pstack);
00363             jpool = (short *)realloc(jpool, sizeof(short) * pstack);
00364             if(ipool == NULL || jpool == NULL)
00365             {
00366               printf("\n Cannot reallocate pool stack, exiting ...\n");
00367               return(15);
00368             }
00369           }
00370           else
00371           {
00372             printf("\n Could not enlarge Pool stack\n");
00373             return(16);
00374           }
00375         }
00376         ipool[npool]=i;
00377         jpool[npool]=j;
00378 /*        printf("%d %d Pool %d\n",i,j,pooln);  */
00379         for(k=1; k<=8; k++)
00380         {  
00381            in=i+d1[k];
00382            jn=j+d2[k];
00383 /* test if neighbor drains towards cell excluding boundaries */
00384            if((dir[jn][in]>0 && (dir[jn][in]-k==4||dir[jn][in]-k==-4))
00385               || (dir[jn][in] == 0 && elev[jn][in] >= elev[j][i]))  
00386                /* so that adjacent flats get included */
00387              {
00388 /*                         if(!(nf == 1   /*  an edge has been found  
00389                                    & elev[jn][in] < et))   /*  Limit recursion below the lowest 
00390                                                                                    edge found  */
00391                                    pool(in,jn);
00392              }
00393  /*          else
00394              {
00395                 et=max2(elev[j][i],elev[jn][in]);
00396                 if(nf == 0)  /*  this is the first edge found  
00397                 {
00398                   emin=et;
00399                   nf=1;
00400                 }
00401                 else
00402                 {
00403                   emin=min2(emin,et);
00404                 }
00405                 }  */
00406         }
00407       }
00408     }
00409   }
00410 
00411      
00412 
00413 float min2(float e1,float e2)
00414 { 
00415   float em; 
00416   em=e1;
00417   if(e2 < em)em=e2;
00418   return(em);
00419 }
00420 
00421 float max2(float e1,float e2)
00422 { 
00423   float em; 
00424   em=e1;
00425   if(e2 > em)em=e2;
00426   return(em);
00427 }
00428 
00429 int addstack(int i, int j)
00430 {
00431         /*  Routine to add entry to is, js stack, enlarging if necessary   */
00432         nis=nis+1;
00433         if(nis >= istack )
00434       {
00435         /*  Try enlarging   */
00436          istack=(int) (istack + nx*ny*.1);
00437          if(istack > nx*ny)
00438          {
00439            printf("\n is,js stack too large, exiting ...\n");
00440            return(12);
00441          }
00442          printf("\n Enlarging is,js stack\n");
00443          is = (short *)realloc(is, sizeof(short) * istack);
00444          js = (short *)realloc(js, sizeof(short) * istack);
00445          dn = (short *)realloc(dn, sizeof(short) * istack);
00446          if(is == NULL || js == NULL || dn == NULL)
00447         {
00448          printf("\n Could not enlarge stack\n");
00449          return(13);
00450         }
00451       }
00452         is[nis]=i;
00453         js[nis]=j;
00454         return(0);
00455 }
00456 
00457 
00458 
00459 
00460 

Generated on Sun Aug 5 17:34:00 2007 for PIHMgis by  doxygen 1.5.2