import java.io.*; class Aslop2 { // Copyleft Harvey Greenberg, UW hgreen@u.washington.edu Dec 8 1997 // This loads an ARC/INFO AAT file into an array of objects (see Aat.java), // processes them, and writes them back out. // Before invoking this class, we have built (in ARCINFO) a river network, // coded the shreve streamorder, and intersected the network with contour lines. // We have determined the to- and from-elevations of most river arcs, but we need // to interpolate and extrapolate to estimate the elevations of (often multiple) // stream junctions. // The first argument is the name of the stream cover. // Optional second argument = the contour interval, used to constrain extrapolation. // The default is 40, though 12.92 might be good for meters, and 121.92 for decimeters. // The otional third argument is the z factor related z units to xy units. // The default is 0.3048, for xy meters and z feet. // The bytelength of the record is hardcoded; this relates to limitations in Arc.java // This was tested on a file of 11000 arcs. There were two arcs which, for // some reason, did not get the elvf or elvt set. // It also failed to deal // automatically with an outlet of shreve order 1, and with a trib junction // which was an outlet. These were handled by manually setting the elvt // variable before invoking this program. // Remember, java defaults to a memory limit of 16 megs. Use the mx switch, // e.g. "java -mx200m Aslop2 mycover" for large data. // or "java -mx200m Aslop2 mycover 121.92 .1" // 1/18/2000: version 3.03. If an arc shows a negative or 0 slope, we assume that // there was an arroneous crossing of a contour. The downstream node // gets set to -99 for that arc and for the downstream arc. // The item "slopeflag" gets set to "F" for these arcs. // Therefore, the string item "slopeflag" is added to the list of // items that must exist on the AAT before this class is run. // 11/7/2001: version 3.1 // Flag each trib segment which is not on mainstem of contour gap. // These segment slopes are a bit suspicious. // Note: This seems to flag the bottom and main legs of a trib triangle. // 4/19/202: version 3.11 Make sure slope and dz are calculated at the start. public static void main (String args[]) throws IOException { Aat myatt; int ishreve,ielvt,ielvf,islope,idz,iflag; double shrevemax,deltaz,theslope; int maxid; float zfactor = 0.3048f; float totlength,interval = 40, tmp1,tmp2,tmp3; double lengthmax; int stringnum,nleft=0,nleftold=0,nup,bestbranch,n; int string_array_max=300; // Max # of arcs between junctions. I saw a 54 on the willapa int arcstring[] = new int[string_array_max+1]; int upid[][] = new int[string_array_max+1][6]; int nbranches[] = new int[string_array_max+1]; String covername; Float ob_interval,ob_zfactor; System.out.println("starting calculation of stream slopes, version 3.11"); if (args.length < 1){ System.out.println("The cover name is a required argument."); return; } else covername = args[0]; if (args.length > 1){ ob_interval = new Float(args[1]); interval = ob_interval.floatValue(); } if (args.length > 2){ ob_zfactor = new Float(args[2]); zfactor = ob_zfactor.floatValue(); } System.out.println("Cover: " + covername + ", contour interval: " + interval + ", zfactor: " + zfactor); try{ myatt = new Aat(covername); } catch (AatError e){ System.out.print("Error loading AAT file:"); System.out.println(e.getMessage()); return; } // System.out.println("AAT has " + myatt.nrecords + " records, " + myatt.nitems + " extra items, " + myatt.extrabytes + " extrabytes, isDoubleodd:" + myatt.isDouble + myatt.odd); myatt.report(); //return; maxid = myatt.nrecords; ishreve = myatt.findItem("shreve"); // i ielvt = myatt.findItem("elvt"); // d ielvf = myatt.findItem("elvf"); // d islope = myatt.findItem("slope"); // d idz = myatt.findItem("dz"); // d iflag = myatt.findItem("slopeflag"); // s if(ishreve < 0) return; if(ielvt < 0) return; if(ielvf < 0) return; if(islope < 0) return; if(idz < 0) return; if(iflag < 0) return; System.out.println("Checking for arcs with negative or zero slopes."); for(int i = 0;i < maxid;i++){ if((myatt.dvalues[ielvt][i] >= myatt.dvalues[ielvf][i]) && myatt.dvalues[ielvf][i] >= 0){ myatt.dvalues[ielvt][i] = -99; // Assume this elevation was from the stream // erroneouly crossing a contour. myatt.dvalues[ielvf][i] = -99; myatt.strings[iflag][i] = "F"; nleft++; for(int j = 0;j < maxid;j++){ if(myatt.fnode[j] == myatt.tnode[i]){ myatt.dvalues[ielvf][j] = -99; myatt.strings[iflag][j] = "F"; nleft++; } if(myatt.tnode[j] == myatt.fnode[i]){ myatt.dvalues[ielvt][j] = -99; myatt.strings[iflag][j] = "F"; nleft++; } } } // zero or negative slope else { //make sure these are done myatt.dvalues[idz][i] = myatt.dvalues[ielvf][i] - myatt.dvalues[ielvt][i]; myatt.dvalues[islope][i] = (float) myatt.dvalues[idz][i] / (float) myatt.length[i] * zfactor; } } // loop through each arc System.out.println(nleft + " arcs had elvt and/or elvf set to null"); for(int hugeit = 1;hugeit < 10;hugeit++){// It drops out after the first iteration // for medium complex topology between // contours. I have never seen it go // beyond 5 iterations. System.out.println("starting huge iteration " + hugeit + "\n"); nleft = 0; bestbranch = 0; stringnum = 1; theslope = 0; // not really needed, but prevents compiler warning message for(int i = 0;i < maxid;i++){ if((myatt.dvalues[ielvt][i] >= 0 || hugeit > 1) && myatt.dvalues[ielvf][i] < 0){ // trace upstream to known elevation nleft++; // System.out.println("starting arc " + i + " ,count=" + nleft); deltaz = -99; totlength = (float) myatt.length[i]; stringnum = 1; arcstring[1] = i; // for(stringnum = 2;stringnum <= string_array_max;stringnum++){ // search up to next contour while(true){ // search up to next contour nup = 0; shrevemax = 0; lengthmax = 0; for(int j = 0;j< maxid;j++){ // System.out.println("1. arcstring[stringnum] = " + arcstring[stringnum] + "j=" + j); if(myatt.tnode[j] == myatt.fnode[arcstring[stringnum]]){ // found upstream arc nup++; upid[stringnum][nup] = j; // remember all branches if(myatt.ivalues[ishreve][j] > shrevemax){ shrevemax = myatt.ivalues[ishreve][j]; bestbranch = j; } else if(myatt.ivalues[ishreve][j] == shrevemax && myatt.length[j] > lengthmax){ lengthmax = myatt.length[j]; bestbranch = j; } } // found upstream arc } // looking for upstream arcs nbranches[stringnum] = nup; if(nup == 0) break; //dangling source stringnum++; totlength += myatt.length[bestbranch]; arcstring[stringnum] = bestbranch; if(myatt.dvalues[ielvf][bestbranch] >= 0) break; // found upstream contour if(stringnum >= string_array_max){ // we should have broken out of the loop System.out.println("Error tracing from arc " + i + " (id=" + myatt.id[i] + ") , or string_array_max undersized."); return; } } // search up to next contour if(stringnum >= string_array_max){ // we should have broken out of the loop System.out.println("An error tracing from arc " + i+ ", or string_array_max undersized."); return; } theslope = -9; //System.out.println("traced up in " + stringnum + "arcs"); if(myatt.dvalues[ielvf][arcstring[stringnum]] < 0){ // dangling source //System.out.println("dangling source" + i + " " + myatt.id[i]); for(int j = 0;j< maxid;j++){ if(myatt.fnode[j] == myatt.tnode[i] && myatt.dvalues[islope][j] > 0.0){ deltaz = myatt.dvalues[islope][j] * totlength / zfactor; if(deltaz > interval) deltaz = interval * 0.8f; //System.out.println("deltaz is " + deltaz); break; } } } //dangling source else if(myatt.dvalues[ielvt][i] < 0){ // dangling mouth for(int j = 0;j< maxid;j++){ if(myatt.tnode[j] == myatt.fnode[arcstring[stringnum]] && myatt.dvalues[islope][j] > 0.0){ deltaz = myatt.dvalues[islope][j] * totlength / zfactor; if(deltaz > interval) deltaz = interval * 0.8f; myatt.dvalues[ielvt][i] = myatt.dvalues[ielvf][arcstring[stringnum]] - deltaz; break; // this would not be a junction } } } //dangling mouth else deltaz = myatt.dvalues[ielvf][arcstring[stringnum]] - myatt.dvalues[ielvt][i]; if(deltaz < 0) continue; // dangling source or mouth to save for next theslope = deltaz / totlength * zfactor; for(int sn = 1;sn <= stringnum;sn++){ // go up the chain, fixing if(myatt.dvalues[ielvf][arcstring[sn]] < 0){ myatt.dvalues[ielvf][arcstring[sn]] = myatt.dvalues[ielvt][arcstring[sn]] + theslope * (float)myatt.length[arcstring[sn]] / zfactor; //nleft--; } myatt.dvalues[idz][arcstring[sn]] = myatt.dvalues[ielvf][arcstring[sn]] - myatt.dvalues[ielvt][arcstring[sn]]; myatt.dvalues[islope][arcstring[sn]] = theslope; // 11/09/2001: The most reliable slopes are from contour to contour on the main channel. Flag the others if(deltaz != interval) myatt.strings[iflag][arcstring[sn]] = "s"; if(sn < stringnum){ for(int k = 1;k <= nbranches[sn];k++){ //if(elvt[upid[sn][k]] < 0) nleft--; myatt.dvalues[ielvt][upid[sn][k]] = myatt.dvalues[ielvf][arcstring[sn]]; if(myatt.dvalues[ielvf][upid[sn][k]] >= 0) { // Finish the arc. 1/6/97 myatt.dvalues[idz][upid[sn][k]] = myatt.dvalues[ielvf][upid[sn][k]] - myatt.dvalues[ielvt][upid[sn][k]]; myatt.dvalues[islope][upid[sn][k]] = (float) myatt.dvalues[idz][upid[sn][k]] / (float) myatt.length[upid[sn][k]] * zfactor; } } // for each upstream branch } } } // this arc needs work else if (myatt.dvalues[idz][i] == 0 && myatt.dvalues[ielvt][i] >= 0 && myatt.dvalues[ielvf][i] >= 0){ //just needs a little work myatt.dvalues[idz][i] = myatt.dvalues[ielvf][i] - myatt.dvalues[ielvt][i]; myatt.dvalues[islope][i] = (float) myatt.dvalues[idz][i] / (float) myatt.length[i] * zfactor; } } // for each arc System.out.println("finished huge iteration " + hugeit + "," + nleft + " more arcs to do\n"); if(nleft == 0) break; // we waste a little time by not decrementing nleft when we fix an arc if(nleft == nleftold) break; nleftold = nleft; } // huge iteration if(nleft != 0)System.out.println("There are still " + nleft + " unfinished arcs. This is probably a problem with the input coverage."); for(int i = 0;i < maxid;i++){ if(myatt.dvalues[ielvt][i] < 0.0 || myatt.dvalues[ielvf][i] < 0.0 || myatt.dvalues[idz][i] <= 0.0) myatt.strings[iflag][i] = "B"; } System.out.println("Writing to to the AAT file."); myatt.writeAat(); } }