package uk.ac.leeds.ccg.raster; import java.lang.*; import java.io.*; import java.net.*; import java.awt.image.*; import java.awt.*; //import java.util.*; import java.util.*; //change for 1.2! import uk.ac.leeds.ccg.geotools.*; /** * A class to hold raster data sets * @author * Ian Turton Centre for * Computaional Geography, University of Leeds, LS2 9JT, 1998.
* i.turton@geog.leeds.ac.uk **/ /** * It is common to want to distinguish between a missing value (nodata) and a * value that is zero or another value that does not effect the result of a * calulation (e.g. The value 0.0d in addition and subtraction, and the value * 1.0d as an exponent power or as a value in a multiplication or the * denominator in a division). * * A default value can be defined as the value which every cell has if it is not * in an (id,list) hashtable containing the other values. In version 1.9 of * Raster the default value was always 0.0d. This was changed to be nodata in * version 1.10 and get and set methods for this value were provided. * * There are advantages in terms of memory usage to using a hashtable if more * than half the values are the default value (because of the need to store the * id otherwise in the hashtable). * * There are various options for Raster storage that should be considered for * geoTools2. The nature of the values in a Raster and its size determine what * what storage is best in terms of memory usage and speed of getting and * setting values. **/ public class Raster extends SimpleGeoData implements Serializable{ private final static boolean DEBUG=true; String name="Raster"; /** * the value below which a cell is considered zero, defaults to 1e-7 * @see #getTol() * @see #setTol() */ double TOL =1e-7; /** * proportion of raster with missing values */ double sparseness; /** * The left hand edge of the raster * @see #getOriginx() * @see #getOrigin() */ protected double originx; /** * The bottom edge of the raster * @see #getOriginy() * @see #getOrigin() */ protected double originy; /** * The cell size of the raster * @see #getCellSize() */ protected double cellsize; /** * The nodata value of the raster * @see #getNoDataValue() */ protected double nodata; /** * GeoData missing value code * double MISSING=Double.NaN; * @see #getMissingValueCode() */ double missing = GeoData.MISSING; /** * The minimum value of the raster * @see #getMin() */ protected double min; protected double nzmin; /** * The maximum value of the raster * @see #getMax() */ protected double max; /** * The height of the raster in cells * @see #getHeight() */ protected int height; /** * The width of the raster in cells * @see #getWidth() */ protected int width; /** * the values of the raster * @see #sparse */ protected double cells[]; /** * Vector to store a sparse raster * @see #sparse */ //private Vector scells = new Vector(1,2000); protected Hashtable scells = new Hashtable(); /** * Is this Raster stored in a sparse form or not * @see #setSparse() * @see #isSparse() */ protected boolean sparse=false; /** * @see #public class MyInt() */ MyInt in = new MyInt(); /** * build a new empty raster of size 0. */ public Raster() { this(new GeoRectangle(),1.0); } /** * builds a new raster from an image. */ public Raster(Image im, int width, int height, GeoRectangle gr) { this(gr,gr.getWidth()/(double)width); double xsize=gr.getWidth()/(double)width; double ysize = gr.getHeight()/(double)(height); if(DEBUG)System.out.println("Ra-->width "+width+" -> "+this.width+" "+xsize); if(DEBUG)System.out.println("Ra-->height "+height+" -> "+this.height+" "+ysize); if(DEBUG)System.out.println("Ra-->cellsize "+cellsize); Canvas obs = new Canvas(); //int width = im.getWidth(obs); //int height = im.getHeight(obs); int[] data = new int[(height*width)]; if(DEBUG)System.out.println("Ra-->image "+width+" by "+height); PixelGrabber pg = new PixelGrabber(im,0,0,width,height,data,0,width); if(DEBUG)System.out.println("Ra-->about to grab"); try { pg.grabPixels(); } catch (InterruptedException e) { System.err.println("Ra-->interrupted waiting for pixels!"); return; } if ((pg.getStatus() & ImageObserver.ABORT) != 0) { System.err.println("Ra-->image fetch aborted or errored"); setBounds(new GeoRectangle()); return ; } if(DEBUG)System.out.println("Ra-->Post grab"); im=null; System.gc(); ColorModel cm = ColorModel.getRGBdefault(); int k=0; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { //int alpha = (data[k] >> 24) & 0xff; //int red = (data[k] >> 16) & 0xff; //int green = (data[k] >> 8) & 0xff; //int blue = (data[k] ) & 0xff; //int alpha = cm.getAlpha(data[k]); //int red = cm.getRed(data[k]); //int green = cm.getGreen(data[k]); //int blue = cm.getBlue(data[k]); //addToCell(originx+i*xsize,originy+j*ysize,(double)green); //addToCell(originx+i*xsize,originy+j*ysize,(double)green); //System.out.println("Ra-->on? "+onSurface(j,i)); addToCell(j,i,(double)(data[k])); //System.out.println("Ra-->"+(j)+ " "+(i)+ " "+red+" "+green+" "+blue+" "+getCell(j,i)); k++; } } } /** * build a new empty raster * @param top the top of the raster in geographic space * @param left the left edge of the raster in geographic space * @param size the cellsize of the raster in geographic units * @param h the height of the raster in cells * @param w the width of the raster in cells */ public Raster(double top, double left, double size, int h, int w){ if(DEBUG)System.out.println("---->uk.ac.leeds.ccg.raster.Raster constructed. Will identify itself as Ra-->"); cellsize=size; originx=left; originx=Math.floor(left/cellsize)*cellsize; // Integerizes originx! originy=top-h; originy=Math.floor(originy/cellsize)*cellsize; // Integerizes originy! height=h; width=w; sparse=true; //cells= new double[h*w]; } public Raster(GeoRectangle m,double size,double[] data){ if(DEBUG)System.out.println("---->uk.ac.leeds.ccg.raster.Raster constructed. Will identify itself as Ra-->"); cellsize=size; originx=m.x; originx=Math.floor(m.x/cellsize)*cellsize; originy=m.y; originy=Math.floor(m.y/cellsize)*cellsize; this.height=(int)Math.round(m.height/cellsize); this.width=(int)Math.round(m.width/cellsize); cells=new double[height*width]; //if(DEBUG)System.out.println("Ra-->h = "+height); //if(DEBUG)System.out.println("Ra-->w = "+width); int p=0; for(int i=0;ip = "+p+" d = "+data[p]); addToCell(i,j,data[p++]); // alternatively putCell(i,j,data[p]); p++; } } if(getSparseness()>50.0d) { setSparse(true); } } public Raster(GeoRectangle m,double size,XYVData[] data){ if(DEBUG)System.out.println("---->uk.ac.leeds.ccg.raster.Raster constructed. Will identify itself as Ra-->"); cellsize=size; originx=m.x; originx=Math.floor(m.x/cellsize)*cellsize; originy=m.y; originy=Math.floor(m.y/cellsize)*cellsize; sparseness=0d; height=(int)Math.round(m.height/cellsize); width=(int)Math.round(m.width/cellsize); sparse=true; scells=new Hashtable(); //cells=new double[height*width]; cells=new double[1]; min=Double.MAX_VALUE; nzmin=Double.MAX_VALUE; max=Double.MIN_VALUE; if(data==null) { min=0.0; max=0.0; return; } for(int i=0;i0.0) nzmin=Math.min(nzmin,data[i].value); } if(getSparseness()<50.0d) { setSparse(false); } } public Raster(GeoRectangle m,double size,RCVData[] data){ cellsize=size; originx=m.x; originx=Math.floor(m.x/cellsize)*cellsize; originy=m.y; originy=Math.floor(m.y/cellsize)*cellsize; sparseness=0d; height=(int)Math.round(m.height/cellsize); width=(int)Math.round(m.width/cellsize); sparse=true; scells=new Hashtable(); //cells=new double[height*width]; min=Double.MAX_VALUE; nzmin=Double.MAX_VALUE; max=Double.MIN_VALUE; if(data==null) return; for(int i=0;i0.0) nzmin=Math.min(nzmin,data[i].value); } if(getSparseness()<50.0d) { setSparse(false); } } public Raster(GeoRectangle m, double size){ if(DEBUG)System.out.println("---->uk.ac.leeds.ccg.raster.Raster constructed. Will identify itself as Ra-->"); cellsize=size; originx=m.x; originx=Math.floor(m.x/cellsize)*cellsize; originy=m.y; originy=Math.floor(m.y/cellsize)*cellsize; sparseness=0d; height=(int)Math.round(m.height/cellsize); width=(int)Math.round(m.width/cellsize); sparse=true; scells=new Hashtable(); cells=new double[1]; } /** * read in an arc/info ascii grid file * @param name the name of the file to read from * @exception IOException if there are any problems with the file */ public Raster(String name) throws java.io.IOException { InputStream in = new FileInputStream(name); ascii(in); } /** * read in an arc/info ascii grid file * @param url the URL to read from * @exception IOException if there are any problems with the file */ public Raster(URL url) throws java.io.IOException { InputStream in = url.openStream(); ascii(in); } private void ascii(InputStream in) throws java.io.IOException { String tok; int type,n; double val,left,bot,size; Reader r = new BufferedReader(new InputStreamReader(in)); StreamTokenizer st = new StreamTokenizer(r); st.parseNumbers(); st.wordChars('_','_'); st.eolIsSignificant(false); st.lowerCaseMode(true); // get ncols type=st.nextToken(); type=st.nextToken(); width=(int)st.nval; // get nrows type=st.nextToken(); type=st.nextToken(); height=(int)st.nval; // get xllcorner type=st.nextToken(); type=st.nextToken(); originx=st.nval; // get yllcorner type=st.nextToken(); type=st.nextToken(); originy=st.nval; // get cellsize type=st.nextToken(); type=st.nextToken(); cellsize=st.nval; // try to get nodata - its optional! type=st.nextToken(); if(type==StreamTokenizer.TT_NUMBER){ st.pushBack(); // put it back if its a number - thats data //nodata=0.0d; nodata=missing; }else{ type=st.nextToken(); nodata=st.nval; System.out.println("nodata set to "+nodata); } st.ordinaryChars('E','E'); // Set array to store the data; cells= new double[height*width]; int pt=0; max=Double.NEGATIVE_INFINITY; min=Double.POSITIVE_INFINITY; /*if (DEBUG) { System.out.println("ncols "+ncols); System.out.println("nrows "+nrows); System.out.println("xllcorner "+xllcorner); System.out.println("yllcorner "+yllcorner); System.out.println("noDataValue "+noDataValue); }*/ // Read and write values. double d1; for(int i=0;i50.0d) { setSparse(true); } } /** * determine if the geographic coordinate given is on the surface. * @param x the x location in geographic units * @param y the y location in geographic units */ public final boolean onSurface(double x,double y){ return(x>=originx&&x=originy&&y=0&&row<(height)&&col>=0&&colh "+(height)+" y "+y+" "+originy+" cell "+cellsize+ //" = "+((((double)(height)*cellsize-y+originy)/cellsize))+ //" = "+((int)Math.round(((double)(height)*cellsize-y+originy)/cellsize))); return((int)Math.floor(((double)(height)*cellsize-y+originy)/cellsize)); } protected final int getCellCol(double x){ return((int)Math.floor((x-originx)/cellsize)); } protected final double getXCell(int col){ return (originx+(double)col*(double)cellsize); } protected final double getYCell(int row){ return (originy+((double)((height)-row)*(double)cellsize)); } /** * convert a geographic location to a pointer to the array of data * @param x the x location in geographic units * @param y the y location in geographic units * @return position in the array */ protected final int getCellPos(double x,double y){ //int row=(int)(((height)*cellsize-y+originy)/cellsize); //int col=(int)((x-originx)/cellsize); int row = getCellRow(y); int col = getCellCol(x); //if(col<0||col>=width)System.out.println("Ra-->X = "+x+"-> "+col+" w "+width); //if(row<0||row>=height)System.out.println("Ra-->Y = "+y+"-> "+row+" h "+height); return getCellID( col, row ); } /** * Converts a x/y grid coordinate to a location in the array of data (ID). * @param xCoord the x coordinate of a gridCell (column) * @param yCoord the y coordinate of a gridCell (row) * @return the ID for this grid coordinate **/ protected final int getCellID( int xCoord, int yCoord ) { return (yCoord * getWidth()) + xCoord; } final public double getTol(){ return TOL; } final public void setTol(double t){ TOL=t; recalc(); } /** * @return the minimium value in the raster */ final public double getMin(){ return min; } final public double getNZMin(){ return nzmin; } /** * @return the maximum value in the raster */ final public double getMax(){ return max; } /** * @param row the row required in cells (from the top). * @param col the column required in cells (from the left). * @return the value at the row and col of the raster. */ final public double getCell(int row,int col){ if(sparse){ in.setValue(row*width+col); Double v=(Double)scells.get(in); if(v!=null){ //if(!v.isNaN()){ //if(DEBUG)System.out.println("Ra--><-"+row+" "+col+" "+in+" "+v); return v.doubleValue(); }else{ //return(0.0d); //return missing; return nodata; } }else{ return(cells[row*width+col]); } } /** * @param x location in geographic space * @param y location in geographic space * @return the value at (x,y) of the raster or GeoData.MISSING * @see uk.ac.leeds.ccg.geotools.GeoData */ final public double getCell(double x,double y){ if(onSurface(x,y)){ int row=getCellRow(y); int col=getCellCol(x); return getCell(row,col); }else{ //return(0.0d); //return missing; return nodata; } } /** * Adds a value to a cell * @param row the row required in cells (from the top). * @param col the column required in cells (from the left). * @param value the value to be added to the cell */ final public double addToCell(int row,int col,double value){ double v=getCell(row,col); if (v!=missing && v!=nodata) { if (value!=nodata && value!=missing) { return putCell(row,col,v+value); } else { // What is in the cell is right already so do nothing! return v; } } else { return putCell(row,col,value); } /* // In some cases this is slower than the above. When what is in the cell is // the correct answer already this still calls the putCell(int,int,double) // method rather than simply returning the answer that it has already got. if (v!=missing && v!=nodata) { if (value!=nodata && value!=missing) { v+=value; } } else { v=value; } return putCell(row,col,v); */ /*if(onSurface(row,col)){ if(sparse){ if(Math.abs(value-0.0d)>TOL){ in.setValue(row*width+col); Double v=(Double)scells.get(in); //if(DEBUG)System.out.println("Ra-->+>"+in+" "+value+" ("+v+")"); if(v!=null){ scells.remove(in); scells.put(in,new Double(v.doubleValue()+value)); min=Math.min(min,v.doubleValue()+value); nzmin=Math.min(nzmin,v.doubleValue()+value); max=Math.max(max,v.doubleValue()+value); }else{ sparseness+=1.0; scells.put(in,new Double(value)); min=Math.min(min,value); nzmin=Math.min(nzmin,value); max=Math.max(max,value); } } }else{ if(Math.abs(value-0.0d)>TOL&&(Math.abs(cells[row*width+col]-0.0d)"+row+" "+col+" off surface"); return -1.0d; } } /** * Puts a value in to the cell at x,y of the raster. * carries out a check to see if the cell is valid and ignores the call * if it is not. * @see #onSurface() */ final public double putCell(double x,double y,double value) { if(onSurface(x,y)) { int row=getCellRow(y); int col=getCellCol(x); return putCell(row,col,value); } return -1.0d; } public double getMissingValueCode(){ return missing; } public void setMissingValueCode(double mv){ missing=mv; } public void setNoDataValue(double d) { nodata=d; setMissingValueCode(d); } public double getNoDataValue() { return nodata; } /** * calculate and return the bounding box of the raster. * @return the bounding box of the raster */ public GeoRectangle getBounds(){ GeoRectangle box = new GeoRectangle(originx,originy,(double)width*(double)cellsize,(double)height*(double)cellsize); //if(DEBUG)System.out.println("Ra-->Ras "+box); return(box); } /** * set the bounds of the raster to a new value * the new bounding box may be larger or smaller as required, if the new * bounding box is smaller information may be lost if it falls outside * the new bounding box. */ public void setBounds(GeoRectangle m){ XYVData[] data=getXYVData(); //if(DEBUG)System.out.println("Ra-->old "+getBounds()); // set the origin to a round number of cellsizes !! originx=Math.floor(m.x/cellsize)*cellsize; //if(DEBUG)System.out.println("Ra-->mx "+m.x+" ox "+originx); originy=Math.floor(m.y/cellsize)*cellsize; //if(DEBUG)System.out.println("Ra-->my "+m.y+" oy "+originy); width=(int)((m.width)/cellsize); height=(int)((m.height)/cellsize); //if(DEBUG)System.out.println("Ra-->new "+getBounds()); sparseness=0.0d; if(sparse) { scells=new Hashtable(); }else{ cells=new double[width*height]; if(data!=null){ for(int i=0;i=width*height){ //return missing; //return 0.0d; return nodata; } if(id<0){ //return missing; //return 0.0d; return nodata; } if(sparse){ in.setValue(id); Double v=(Double)scells.get(in); if(v!=null){ return v.doubleValue(); }else{ //return 0.0d; //return missing; return nodata; } }else{ return(cells[id]); } } /** * @return the size of the raster in cells */ public int getSize(){ return(height*width); } public String getText(int id){ return new Double(getValue(id)).toString(); } /** * @return if the raster is stored sparsly */ public boolean isSparse(){ return sparse; } /** * change if the raster is to be stored in a sparse form * @param flag the state to be set. */ public void setSparse(boolean flag){ if(flag==sparse) return; if(flag==true){ switchtosparse(); }else{ switchtofull(); } } private void recalc(){ //public void recalc(){ int p=0; if(sparse){ switchtofull(); if(getSparseness()>50)switchtosparse(); }else{ switchtosparse(); if(getSparseness()<50)switchtofull(); } } private void switchtosparse(){ int p=0; sparseness=0d; sparse=true; for(int i=0;iTOL){ //if (cells[p]!=nodata) { putCell(i,j,cells[p]); //} p++; } } cells=new double[1]; System.gc();// we need to free cells return; } private void switchtofull(){ int p=0; cells=new double[height*width]; for(int i=0;i"+i+" "+j+" "+(i*width+j)+" "+in[i*width+j]); putCell(i,j,in[i*width+j]); //if(DEBUG)System.out.println("Ra-->"+in[i*width+j]+" "+getCell(i,j)); } } if(getSparseness()>50.0d&&isSparse()==false) { if(DEBUG)System.out.println("Ra-->Going sparse"); setSparse(true); } if(getSparseness()<50.0d&&isSparse()==true) { if(DEBUG)System.out.println("Ra-->Going full"); setSparse(false); } } /** * set cellsize */ public void setCellSize(double d) { cellsize=d; } /** * internal class that stores raster data in row column value form * @see #XYVData */ static class RCVData{ int row,col; double value; } /** * internal class that stores raster data in geographic coordinates value */ class XYVData{ double x,y; double value; } /** * save a raster to the file named in name. * @throws java.io.IOException * @deprecated new programs should use writeObject. */ public void save(String name) throws java.io.IOException{ DataOutputStream out = new DataOutputStream(new FileOutputStream(name)); out.writeUTF(this.name); out.writeDouble(originx); out.writeDouble(originy); out.writeInt(height); out.writeInt(width); out.writeDouble(cellsize); out.writeDouble(nodata); //out.writeDouble(TOL); out.writeBoolean(sparse); out.writeDouble(sparseness); if(sparse){ RCVData a[]=getRCVData(); for(int i=0;i"+i+" "+j+" "+val); if(Math.abs(val-0.0d)>=TOL){ p++; out[p]=new XYVData(); out[p].value=val; out[p].x=getXCell(j); out[p].y=getYCell(i); //if(DEBUG)System.out.println("Ra-->j "+j+" -> x "+out[p].x); //if(DEBUG)System.out.println("Ra-->i "+i+" -> y "+out[p].y); } } } p++; if(p!=0)return(out); else return null; } public RCVData[] getRCVData(){ RCVData out[]=new RCVData[(int)sparseness]; double val; int p=0; for(int i=0;iTOL){ out[p]=new RCVData(); out[p].value=val; out[p].row=i; out[p].col=j; p++; } } } return(out); } public Object clone(){ //if(DEBUG)System.out.println("Ra-->cloning "); Raster t= new Raster(getBounds(),getCellSize(),(XYVData[])null); t.sparse = this.sparse; t.sparseness = this.sparseness; t.TOL = this.TOL; if(t.sparse){ t.scells=(Hashtable)this.scells.clone(); }else{ t.cells=new double[width*height]; System.arraycopy(this.cells,0,t.cells,0,this.cells.length); } t.min=this.min; t.nzmin=this.nzmin; t.max=this.max; return t; } /** * @param a the raster to be added * @exception RasterMathException if the raster cellsizes differ */ public Raster RasterMath(Raster a,RasterOp op) throws RasterMathException{ if(a==null) { throw new RasterMathException("Null Raster"); } if(getCellSize()!=a.getCellSize()){ // this won't work if the rasters are different scales throw new RasterMathException("Cell Size Mismatch\n "+getName()+" "+getCellSize()+" "+a.getName()+" "+a.getCellSize()); } GeoRectangle out = new GeoRectangle(getBounds()); out.add(a.getBounds()); //Raster t1=(Raster)this.clone(); Raster t1=this; GeoRectangle inter = getBounds().createIntersect(a.getBounds()); t1.setBounds(out); //Raster t2 = new Raster(out,cellsize,d2); //Raster t2=(Raster)a.clone(); Raster t2=a; //t2.setBounds(out); //t1.setName(getName()); //t2.setName(a.getName()); Raster t3 = new Raster(out,cellsize,(RCVData [])null); if(t1.getSparseness()==100.0d){ return (Raster)t2.clone(); } if(t2.getSparseness()==100.0d){ return (Raster)t1.clone(); } // now step through the two rasters applying op to them. if(!(t1.sparse&&t2.sparse)){ // if they are both sparse we can save time by just working through the non-zero cells double v; t3.setName("Output"); t3.min=Double.MAX_VALUE; t3.nzmin=Double.MAX_VALUE; t3.max=Double.MIN_VALUE; for(int i=0;i0.0) t3.nzmin=Math.min(t3.nzmin,v); t3.max=Math.max(t3.max,v); t3.putCell(i,j,v); } } } return t3; }else{ Double v1,v2; double v; t3.min=Double.MAX_VALUE; t3.nzmin=Double.MAX_VALUE; t3.max=Double.MIN_VALUE; MyInt pos; // this probably doesn't work properly if a op b != b op a and 0 is not an identity operation. java.util.Enumeration k = t1.scells.keys(); while (k.hasMoreElements()){ pos = (MyInt) k.nextElement(); v1=(Double)t1.scells.get(pos); if(t2.scells.containsKey(pos)){ v2=(Double)t2.scells.get(pos); v=op.calc(v1.doubleValue(),v2.doubleValue()); }else{ v=op.calc(v1.doubleValue(),0.0d); } if(Math.abs(v-0.0d)>TOL){ t3.sparseness++; } if(!Double.isInfinite(v)&&!Double.isNaN(v)){ t3.scells.put(pos, new Double(v)); t3.min=Math.min(t3.min,v); if(v>0.0) t3.nzmin=Math.min(t3.nzmin,v); if(v!=Double.POSITIVE_INFINITY)t3.max=Math.max(t3.max,v); } } if(t3.min>0.0d) t3.min=0.0d; // no zeros in a sparse raster return t3; } } public final Raster RasterMath(double a,RasterOp op) throws RasterMathException{ double v; Raster t1=(Raster)this.clone(); if(a==0.0d&&op instanceof mult){ // mult by zero is zero t1.scells=new Hashtable(); t1.cells=new double[1]; t1.min=0.0d; t1.max=0.0d; t1.sparse=true; t1.sparseness=0.0; return t1; } if(a==1.0d&&(op instanceof mult||op instanceof divide)){ // identity return t1; } if(a==0.0d&&(op instanceof add||op instanceof sub)){ // identity return t1; } t1.min=Double.MAX_VALUE; t1.max=Double.MIN_VALUE; if(!t1.sparse){ for(int i=0;i0.0)t1.nzmin=Math.min(t1.nzmin,v); t1.max=Math.max(t1.max,v); t1.putCell(i,j,v); } } }else{ /* sparse*/ Double v1; MyInt pos; java.util.Enumeration k = t1.scells.keys(); while (k.hasMoreElements()){ pos = (MyInt) k.nextElement(); v1=(Double)t1.scells.get(pos); t1.scells.remove(pos); v=op.calc(v1.doubleValue(),a); if(Math.abs(v-0.0d)>TOL&&Math.abs(v1.doubleValue()-0.0d)0.0d)t1.min=0.0d; // if its sparse then we haven't seen any zeros } return t1; } public java.util.Enumeration getIds(){ return new ID(); } class ID implements java.util.Enumeration{ boolean more = true; int next=0; public boolean hasMoreElements(){ return more; } public Object nextElement(){ Integer n = new Integer(next++); if(next>width*height){ more = false; } return n; } } private void writeObject(java.io.ObjectOutputStream out) throws IOException{ out.writeUTF(this.name); out.writeDouble(originx); out.writeDouble(originy); out.writeInt(height); out.writeInt(width); out.writeDouble(cellsize); out.writeDouble(nodata); //out.writeDouble(TOL); out.writeBoolean(sparse); out.writeDouble(sparseness); if(sparse){ RCVData a[]=getRCVData(); for(int i=0;iLoaded 1st file "+((inter-start)/1000)); start=System.currentTimeMillis(); in = new ObjectInputStream(new BufferedInputStream(new FileInputStream("/home/preston/ian/java/javashape/w3pop4.ras"),10000)); t2=(Raster)in.readObject(); inter=System.currentTimeMillis(); if(DEBUG)System.out.println("Ra-->Loaded 2nd file "+((inter-start)/1000)); } catch(IOException e){System.out.println("Ra-->ArcInfo Load Failed "+e);} catch(ClassNotFoundException cne){System.out.println("Ra-->Class not found "+cne);} try{ start=System.currentTimeMillis(); t1=t1.RasterMath(t2,new add()); inter=System.currentTimeMillis(); if(DEBUG)System.out.println("Ra-->added "+((inter-start)/1000)); }catch(RasterMathException e){System.out.println("Ra-->"+e);} } /* this sort of fudges the changes up to the layer */ Vector listeners = new Vector(); public void removeChangedListener(ChangedListener lcl) { listeners.removeElement(lcl); } public void addChangedListener(ChangedListener lcl){ listeners.addElement(lcl); } public void notifyChangedListeners(int reason){ Vector l; ChangedEvent lce = new ChangedEvent(this,reason); synchronized(this) {l = (Vector)listeners.clone(); } for (int i = 0; i < l.size();i++) { ((ChangedListener)l.elementAt(i)).Changed(lce); } } public void writeArcGrid(File f){ BufferedOutputStream os ; try{ os = new BufferedOutputStream(new FileOutputStream(f)); }catch(Exception e){System.err.println("Ra-->Error in save "+e);return;} PrintWriter pw = new PrintWriter(os); pw.println("Ncols "+width+"\nnrows "+height); pw.println("xllcorner "+originx+"\nyllcorner "+originy); pw.println("cellsize "+cellsize); pw.println("NODATA_value "+nodata); for(int j=0;j