001/* 002 * Copyright (c) 2003-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030/** 031 * Name: Grid.java 032 * Purpose: Used to represent georeferenced grids of values; includes 033 * methods for manipulating those grids. especially regridding. 034 * The emphasis is on equally spaced grids (like those described in 035 * *.ASC files). 036 * 037 * Author : Dan Higgins 038 * 039 */ 040 041package org.ecoinformatics.seek.gis.java_gis; 042 043import java.awt.Shape; 044import java.io.BufferedReader; 045import java.io.File; 046import java.io.FileNotFoundException; 047import java.io.FileOutputStream; 048import java.io.FileReader; 049import java.io.PrintWriter; 050import java.util.Hashtable; 051import java.util.StringTokenizer; 052 053import util.PersistentVector; 054 055public class Grid { 056 057 public int nrows; 058 public int ncols; 059 060 public double xllcorner; 061 public double yllcorner; 062 public double delx; 063 public double dely; 064 // ASC files have square cells; i.e. a cellsize = delx = dely 065 // we make it slightly more general here 066 public static String NODATA_value_String = "-9999"; 067 068 public boolean inMemFlag = false; 069 070 // assume a cell is defined by row and column index of upper left corner 071 // and there is a numeric value associated with each cell 072 073 public double[][] dataArray = null; 074 public PersistentVector pv = null; 075 076 // last row string array;used to speed up access when PersistenVector is 077 // used 078 private String[] rowSA = null; 079 // last row index 080 private int last_y = -1; 081 // next to last row string array;used to speed up access when 082 // PersistenVector is used 083 private String[] next2lastrowSA = null; 084 // next to last row index 085 private int next2last_y = -1; 086 087 private String cachedLine = ""; 088 private Hashtable header = null; 089 090 private double no_val_threshold = 1.0E100; 091 092 static final int NEAREST_NEIGHBOR = 0; 093 static final int INVERSE_DISTANCE = 1; 094 095 public Grid() { 096 // just generate a simple grid 097 nrows = 10; 098 ncols = 10; 099 delx = 1.0; 100 dely = 1.0; 101 xllcorner = 0.0; 102 yllcorner = 0.0; 103 // note that no data storage for grid values has been created 104 } 105 106 public Grid(int nx, int ny, double dx, double dy, double xmin, double ymin) { 107 this.ncols = nx; 108 this.nrows = ny; 109 this.delx = dx; 110 this.dely = dy; 111 this.xllcorner = xmin; 112 this.yllcorner = ymin; 113 // note that no data storage for grid values has been created 114 } 115 116 // create a Grid from an .ASC file 117 public Grid(File ascfile) { 118 FileReader inReader = null; 119 BufferedReader bufReader = null; 120 try { 121 inReader = new FileReader(ascfile); 122 bufReader = new BufferedReader(inReader); 123 header = getHeaderInformation(bufReader); 124 } catch (Exception ee) { 125 System.out.println("Exception at main!"); 126 } 127 // first non-header line should be in cachedLine string 128 // and header values should be in header hash 129 // test 130 // System.out.println("header hash: "+header); 131 if (header.containsKey("NODATA_value")) { 132 NODATA_value_String = (String) header.get("NODATA_value"); 133 } 134 nrows = (new Integer((String) header.get("nrows"))).intValue(); 135 ncols = (new Integer((String) header.get("ncols"))).intValue(); 136 delx = (new Double((String) header.get("cellsize"))).doubleValue(); 137 dely = (new Double((String) header.get("cellsize"))).doubleValue(); 138 xllcorner = (new Double((String) header.get("xllcorner"))) 139 .doubleValue(); 140 yllcorner = (new Double((String) header.get("yllcorner"))) 141 .doubleValue(); 142 143 if (inMemFlag) { 144 // now create the actual data array 145 dataArray = new double[ncols][nrows]; 146 int i = 0; 147 int j = 0; 148 while (cachedLine != null) { 149 StringTokenizer st = new StringTokenizer(cachedLine); 150 i = 0; 151 while (st.hasMoreTokens()) { 152 String nextToken = st.nextToken().trim(); 153 if (!nextToken.equals(NODATA_value_String)) { 154 double val = Double.parseDouble(nextToken); 155 dataArray[i][j] = val; 156 } else { 157 // missing value 158 dataArray[i][j] = 1.0E101; 159 } 160 i++; 161 } 162 try { 163 cachedLine = bufReader.readLine(); 164 j++; 165 } catch (Exception eee) { 166 cachedLine = null; 167 } 168 } 169 } else { 170 171 // an ObjectFile version 172 173 pv = new PersistentVector(); 174 pv.setFirstRow(6); 175 pv.setFieldDelimiter("#x20"); 176 System.out.println("filename: " + ascfile.getPath()); 177 pv.init(ascfile.getPath()); 178 } 179 try { 180 bufReader.close(); 181 } catch (Exception w) { 182 System.out.println("Error in creating grid from asc file!"); 183 } 184 185 } 186 187 // used to create a Grid from ASC file and determine whether to save it in 188 // memory (or use disk) 189 public Grid(File ascfile, boolean inMemory) { 190 inMemFlag = inMemory; 191 FileReader inReader = null; 192 BufferedReader bufReader = null; 193 try { 194 inReader = new FileReader(ascfile); 195 bufReader = new BufferedReader(inReader); 196 header = getHeaderInformation(bufReader); 197 } catch (Exception ee) { 198 System.out.println("Exception at main!"); 199 } 200 // first non-header line should be in cachedLine string 201 // and header values should be in header hash 202 // test 203 // System.out.println("header hash: "+header); 204 if (header.containsKey("NODATA_value")) { 205 NODATA_value_String = (String) header.get("NODATA_value"); 206 } 207 nrows = (new Integer((String) header.get("nrows"))).intValue(); 208 ncols = (new Integer((String) header.get("ncols"))).intValue(); 209 delx = (new Double((String) header.get("cellsize"))).doubleValue(); 210 dely = (new Double((String) header.get("cellsize"))).doubleValue(); 211 xllcorner = (new Double((String) header.get("xllcorner"))) 212 .doubleValue(); 213 yllcorner = (new Double((String) header.get("yllcorner"))) 214 .doubleValue(); 215 216 if (inMemFlag) { 217 // now create the actual data array 218 dataArray = new double[ncols][nrows]; 219 int i = 0; 220 int j = 0; 221 while (cachedLine != null) { 222 StringTokenizer st = new StringTokenizer(cachedLine); 223 i = 0; 224 while (st.hasMoreTokens()) { 225 String nextToken = st.nextToken().trim(); 226 if (!nextToken.equals(NODATA_value_String)) { 227 double val = Double.parseDouble(nextToken); 228 dataArray[i][j] = val; 229 } else { 230 // missing value 231 dataArray[i][j] = 1.0E101; 232 } 233 i++; 234 } 235 try { 236 cachedLine = bufReader.readLine(); 237 j++; 238 } catch (Exception eee) { 239 cachedLine = null; 240 } 241 } 242 } else { 243 244 // an ObjectFile version 245 246 pv = new PersistentVector(); 247 pv.setFirstRow(6); 248 pv.setFieldDelimiter("#x20"); 249 System.out.println("filename: " + ascfile.getPath()); 250 pv.init(ascfile.getPath()); 251 } 252 try { 253 bufReader.close(); 254 } catch (Exception w) { 255 System.out.println("Error in creating grid from asc file!"); 256 } 257 } 258 259 // Note that the data is indexed from the top left, not the lower left 260 public double getValue(int x, int y) { 261 String val; 262 double ret = 1.0E101; // assume any number > than no_val_threshold is 263 // missing data 264 if ((x < 0) || (x > ncols - 1)) 265 return ret; // outside grid 266 if ((y < 0) || (y > nrows - 1)) 267 return ret; // outside grid 268 // assume for now that the array is in memory 269 if (dataArray != null) { 270 ret = dataArray[x][y]; 271 } 272 if (pv != null) { 273 if ((y != next2last_y) && (y != last_y)) { 274 next2last_y = last_y; 275 next2lastrowSA = rowSA; 276 rowSA = (String[]) (pv.elementAt(y)); 277 last_y = y; 278 } 279 if (y == last_y) { 280 val = rowSA[x]; 281 } else { 282 val = next2lastrowSA[x]; 283 } 284 if (val.equals(NODATA_value_String)) { 285 ret = 1.0E101; 286 } else { 287 ret = new Double(val).doubleValue(); 288 } 289 } 290 return ret; 291 } 292 293 // Note that the data is indexed from the top left, not the lower left 294 // but the location is described from the lowerleft corner (as doubles) 295 public double interpValue(double x, double y, int scalingAlgorithm) { 296 x = x + .01 * delx; // slight shift to avoid round off problems - DFH 297 y = y - .01 * dely; // slight shift to avoid round off problems - DFH 298 if (scalingAlgorithm == INVERSE_DISTANCE) { 299 return interpValue_IDW(x, y); 300 } 301 double ret = 1.0E101; 302 int xint = (int) ((x - xllcorner) / delx); 303 int yint = nrows - 1 - (int) ((y - yllcorner) / dely); 304 if (yint == -1) 305 yint = 0; 306 ret = getValue(xint, yint); 307 return ret; 308 } 309 310 public double interpValue_IDW(double x, double y) { 311 int delij = 1; 312 int deliij = 1; 313 int delijj = 1; 314 int deliijj = 1; 315 double ret = 1.0E101; 316 int xint = (int) ((x - xllcorner) / delx); 317 int yint = nrows - 1 - (int) ((y - yllcorner) / dely); 318 if (yint == -1) 319 yint = 0; 320 if (xint >= ncols - 1) 321 xint = ncols - 2; 322 if (yint >= nrows - 1) 323 yint = nrows - 2; 324 double valij = getValue(xint, yint); 325 double valiij = getValue(xint + 1, yint); 326 double valijj = getValue(xint, yint + 1); 327 double valiijj = getValue(xint + 1, yint + 1); 328 if ((valij >= no_val_threshold) && (valiij >= no_val_threshold) 329 && (valijj >= no_val_threshold) 330 && (valiijj >= no_val_threshold)) { 331 return ret; 332 } 333 // no_values are often set at boundaries; i.e. oceans 334 // in order to interpolate near these boundaries, the values 335 // of cells with no data must be ignored. The checks below implement 336 // this. 337 if (valij >= no_val_threshold) 338 delij = 0; 339 if (valiij >= no_val_threshold) 340 deliij = 0; 341 if (valijj >= no_val_threshold) 342 delijj = 0; 343 if (valiijj >= no_val_threshold) 344 deliijj = 0; 345 346 // calculate distances to enclosing grid points. 347 // if the distance is very small, just return the value at the corner 348 // since 349 // it will dominate anyway 350 double dist2center = (delx * delx + dely * dely) / 4.0; 351 double distij2 = ((x - xllcorner) % delx) * ((x - xllcorner) % delx) 352 + ((dely - (y - yllcorner) % dely)) 353 * ((dely - (y - yllcorner) % dely)); 354 if (distij2 < 1E-99) 355 return valij; 356 if ((distij2 < dist2center) && (delij == 0)) 357 return valij; 358 double distiij2 = ((delx - (x - xllcorner) % delx)) 359 * ((delx - (x - xllcorner) % delx)) 360 + ((dely - (y - yllcorner) % dely)) 361 * ((dely - (y - yllcorner) % dely)); 362 if (distiij2 < 1E-99) 363 return valiij; 364 if ((distiij2 < dist2center) && (deliij == 0)) 365 return valiij; 366 double distijj2 = ((x - xllcorner) % delx) * ((x - xllcorner) % delx) 367 + ((y - yllcorner) % dely) * ((y - yllcorner) % dely); 368 if (distijj2 < 1E-99) 369 return valijj; 370 if ((distijj2 < dist2center) && (delijj == 0)) 371 return valijj; 372 double distiijj2 = ((delx - (x - xllcorner) % delx)) 373 * ((delx - (x - xllcorner) % delx)) + ((y - yllcorner) % dely) 374 * ((y - yllcorner) % dely); 375 if (distiijj2 < 1E-99) 376 return valiijj; 377 if ((distiijj2 < dist2center) && (deliijj == 0)) 378 return valiijj; 379 380 double weightij = delij / distij2; 381 double weightiij = deliij / distiij2; 382 double weightijj = delijj / distijj2; 383 double weightiijj = deliijj / distiijj2; 384 double sumw = weightij + weightiij + weightijj + weightiijj; 385 386 ret = (valij * weightij + valiij * weightiij + valijj * weightijj + valiijj 387 * weightiijj) 388 / sumw; 389 390 return ret; 391 } 392 393 public void createAsc(String filename) { 394 PrintWriter out = null; 395 try { 396 out = new PrintWriter(new FileOutputStream(filename)); 397 out.print("nrows " + nrows); 398 out.println(); 399 out.print("ncols " + ncols); 400 out.println(); 401 out.print("xllcorner " + xllcorner); 402 out.println(); 403 out.print("yllcorner " + yllcorner); 404 out.println(); 405 out.print("cellsize " + delx); 406 out.println(); 407 out.print("NODATA_value " + NODATA_value_String); 408 out.println(); 409 if (dataArray != null) { 410 for (int r = 0; r < nrows; r++) { 411 for (int c = 0; c < ncols; c++) { 412 double val = dataArray[c][r]; 413 if (val > no_val_threshold) { 414 out.print(NODATA_value_String + " "); 415 } else { 416 out.print(val + " "); 417 } 418 } 419 out.println(); 420 } 421 } 422 if (pv != null) { 423 for (int r = 0; r < nrows; r++) { 424 String[] rs = (String[]) pv.elementAt(r); 425 String temp = ""; 426 for (int c = 0; c < ncols; c++) { 427 temp = temp + rs[c] + " "; 428 } 429 out.println(temp); 430 } 431 } 432 out.close(); 433 } catch (FileNotFoundException e) { 434 System.out.println("Problem creating Asc File!"); 435 } 436 } 437 438 // rescale this grid as indicated using nearest neighbor 439 public Grid rescale(int nr, int nc, double dx, double dy, double xmin, 440 double ymin, int scalingAlgorithm) { 441 Grid newGrid = new Grid(nc, nr, dx, dy, xmin, ymin); 442 if (inMemFlag && (dataArray != null)) { 443 double[][] newDataArray = new double[nc][nr]; 444 newGrid.dataArray = newDataArray; 445 for (int j = 0; j < nr; j++) { 446 // System.out.println("Working on row # "+j); 447 double yloc = ymin + nr * dy - j * dy; 448 for (int i = 0; i < nc; i++) { 449 double xloc = xmin + i * dx; 450 double val = this.interpValue(xloc, yloc, scalingAlgorithm); 451 newDataArray[i][j] = val; 452 } 453 } 454 } else { // using PersistentVector for data storage 455 newGrid.pv = new PersistentVector(); 456 newGrid.pv.setFirstRow(6); 457 newGrid.pv.setFieldDelimiter("#x20"); 458 String[] rowvals = new String[nc]; 459 for (int j = 0; j < nr; j++) { 460 // System.out.println("Working on row # "+j); 461 double yloc = ymin + nr * dy - j * dy; 462 for (int i = 0; i < nc; i++) { 463 double xloc = xmin + i * dx; 464 double val = this.interpValue(xloc, yloc, scalingAlgorithm); 465 String valStr; 466 if (val > no_val_threshold) { 467 valStr = NODATA_value_String; 468 } else { 469 valStr = (new Double(val)).toString(); 470 } 471 rowvals[i] = valStr; 472 } 473 newGrid.pv.addElement(rowvals); 474 rowvals = new String[nc]; // needed to make sure new object 475 // added to pv 476 } 477 } 478 return newGrid; 479 } 480 481 // reset values in range (minval,maxval) to newvalue 482 public Grid reset(double minval, double maxval, double newvalue) { 483 // create a new Grid with same parameters as this one 484 Grid newGrid = new Grid(ncols, nrows, delx, dely, xllcorner, yllcorner); 485 if (inMemFlag && (dataArray != null)) { 486 double[][] newDataArray = new double[ncols][nrows]; 487 newGrid.dataArray = newDataArray; 488 for (int j = 0; j < nrows; j++) { 489 for (int i = 0; i < ncols; i++) { 490 double val = this.getValue(i, j); 491 if ((val > minval) && (val < maxval)) 492 val = newvalue; 493 newDataArray[i][j] = val; 494 } 495 } 496 } else { // using PersistentVector for data storage 497 newGrid.pv = new PersistentVector(); 498 newGrid.pv.setFirstRow(6); 499 newGrid.pv.setFieldDelimiter("#x20"); 500 String[] rowvals = new String[ncols]; 501 for (int j = 0; j < nrows; j++) { 502 for (int i = 0; i < ncols; i++) { 503 double val = this.getValue(i, j); 504 if ((val > minval) && (val < maxval)) 505 val = newvalue; 506 String valStr; 507 if (val > no_val_threshold) { 508 valStr = NODATA_value_String; 509 } else { 510 valStr = (new Double(val)).toString(); 511 } 512 rowvals[i] = valStr; 513 } 514 newGrid.pv.addElement(rowvals); 515 rowvals = new String[ncols]; // needed to make sure new object 516 // added to pv 517 } 518 } 519 return newGrid; 520 } 521 522 // transform values in range (minval,maxval) to by a multiplication and/or 523 // addition 524 public Grid transform(double minval, double maxval, double multFactor, 525 double addFactor) { 526 // create a new Grid with same parameters as this one 527 Grid newGrid = new Grid(ncols, nrows, delx, dely, xllcorner, yllcorner); 528 if (inMemFlag && (dataArray != null)) { 529 double[][] newDataArray = new double[ncols][nrows]; 530 newGrid.dataArray = newDataArray; 531 for (int j = 0; j < nrows; j++) { 532 for (int i = 0; i < ncols; i++) { 533 double val = this.getValue(i, j); 534 if ((val > minval) && (val < maxval)) { 535 val = multFactor * val + addFactor; 536 } 537 newDataArray[i][j] = val; 538 } 539 } 540 } else { // using PersistentVector for data storage 541 newGrid.pv = new PersistentVector(); 542 newGrid.pv.setFirstRow(6); 543 newGrid.pv.setFieldDelimiter("#x20"); 544 String[] rowvals = new String[ncols]; 545 for (int j = 0; j < nrows; j++) { 546 for (int i = 0; i < ncols; i++) { 547 double val = this.getValue(i, j); 548 if ((val > minval) && (val < maxval)) { 549 val = multFactor * val + addFactor; 550 } 551 String valStr; 552 if (val > no_val_threshold) { 553 valStr = NODATA_value_String; 554 } else { 555 valStr = (new Double(val)).toString(); 556 } 557 rowvals[i] = valStr; 558 } 559 newGrid.pv.addElement(rowvals); 560 rowvals = new String[ncols]; // needed to make sure new object 561 // added to pv 562 } 563 } 564 return newGrid; 565 } 566 567 public int getNumberMissingDataPixels() { 568 int cnt = 0; 569 if (dataArray != null) { // in memory 570 for (int i = 0; i < ncols; i++) { 571 for (int j = 0; j < nrows; j++) { 572 double val = getValue(i, j); 573 if (val > no_val_threshold) 574 cnt++; 575 } 576 } 577 return cnt; 578 } 579 if (pv != null) { 580 for (int j = 0; j < nrows; j++) { 581 String[] rowSA = (String[]) (pv.elementAt(j)); 582 for (int i = 0; i < ncols; i++) { 583 String val = rowSA[i]; 584 if (val.equals(NODATA_value_String)) { 585 cnt++; 586 } 587 } 588 } 589 } 590 return cnt; 591 } 592 593 // remove this Grid object 594 // in particular, delete the potentially large Object file associated with 595 // the PersistentVector 596 public void delete() { 597 if (pv != null) { 598 pv.delete(); 599 pv = null; 600 } 601 if (dataArray != null) { 602 dataArray = null; 603 } 604 } 605 606 public double getFractionMissingDataPixels() { 607 double frac = ((double) getNumberMissingDataPixels()) / (ncols * nrows); 608 return frac; 609 } 610 611 // count the pixels with value 'val' within the distance 'thresh' 612 public int getNumberPixelsWithValue(double val, double thresh) { 613 double tval; 614 int cnt = 0; 615 if (dataArray != null) { // in memory 616 for (int i = 0; i < ncols; i++) { 617 for (int j = 0; j < nrows; j++) { 618 double temp = getValue(i, j); 619 if (Math.abs(temp - val) < thresh) 620 cnt++; 621 } 622 } 623 return cnt; 624 } 625 if (pv != null) { 626 for (int j = 0; j < nrows; j++) { 627 String[] rowSA = (String[]) (pv.elementAt(j)); 628 for (int i = 0; i < ncols; i++) { 629 String ts = rowSA[i]; 630 if (!(ts.equals(NODATA_value_String))) { 631 tval = new Double(ts).doubleValue(); 632 if (Math.abs(tval - val) < thresh) 633 cnt++; 634 } 635 } 636 } 637 } 638 return cnt; 639 } 640 641 // get fraction of nonMissing data pixels with value 642 public double getFractionPixelsWithValue(double val, double thresh) { 643 double frac = ((double) getNumberPixelsWithValue(val, thresh)) 644 / ((ncols * nrows) - getNumberMissingDataPixels()); 645 return frac; 646 } 647 648 // createRectangularMask takes this grid and sets alls cells outside the 649 // specified rectangle to one value and all cells inside to another 650 public void createRectangularMask(double xmin, double ymin, double xmax, 651 double ymax, double outvalue, double invalue) { 652 String invalueStr; 653 if (invalue > no_val_threshold) { 654 invalueStr = NODATA_value_String; 655 } else { 656 invalueStr = (new Double(invalue)).toString(); 657 } 658 String outvalueStr; 659 if (outvalue > no_val_threshold) { 660 outvalueStr = NODATA_value_String; 661 } else { 662 outvalueStr = (new Double(outvalue)).toString(); 663 } 664 665 if (inMemFlag && (dataArray != null)) { 666 for (int j = 0; j < nrows; j++) { 667 double yloc = yllcorner + nrows * dely - j * dely; 668 for (int i = 0; i < ncols; i++) { 669 double xloc = xllcorner + i * delx; 670 if ((xloc > xmin) && (xloc < xmax)) { 671 if ((yloc > ymin) && (yloc < ymax)) { 672 // inside the rectangle 673 dataArray[i][j] = invalue; 674 } 675 } else { 676 dataArray[i][j] = outvalue; 677 } 678 } 679 } 680 } else { // using PersistentVector for data storage 681 if (pv == null) { 682 pv = new PersistentVector(); 683 pv.setFirstRow(6); 684 pv.setFieldDelimiter("#x20"); 685 } 686 String[] rowvals = new String[ncols]; 687 for (int j = 0; j < nrows; j++) { 688 double yloc = yllcorner + nrows * dely - j * dely; 689 for (int i = 0; i < ncols; i++) { 690 double xloc = xllcorner + i * delx; 691 if ((xloc > xmin) && (xloc < xmax)) { 692 if ((yloc > ymin) && (yloc < ymax)) { 693 // inside the rectangle 694 rowvals[i] = (new Double(invalue)).toString(); 695 } 696 } else { 697 rowvals[i] = (new Double(outvalue)).toString(); 698 } 699 } 700 pv.addElement(rowvals); 701 rowvals = new String[ncols]; // needed to make sure new object 702 // added to pv 703 } 704 705 } 706 } 707 708 // createShapeMask takes this grid and sets alls cells outside the 709 // specified Shape to one value and all cells inside to another 710 public void createShapeMask(Shape shape, double outvalue, double invalue) { 711 String invalueStr; 712 if (invalue > no_val_threshold) { 713 invalueStr = NODATA_value_String; 714 } else { 715 invalueStr = (new Double(invalue)).toString(); 716 } 717 String outvalueStr; 718 if (outvalue > no_val_threshold) { 719 outvalueStr = NODATA_value_String; 720 } else { 721 outvalueStr = (new Double(outvalue)).toString(); 722 } 723 724 if (inMemFlag && (dataArray != null)) { 725 for (int j = 0; j < nrows; j++) { 726 double yloc = yllcorner + nrows * dely - j * dely; 727 for (int i = 0; i < ncols; i++) { 728 double xloc = xllcorner + i * delx; 729 if (shape.contains(xloc, yloc)) { 730 // inside the rectangle 731 dataArray[i][j] = invalue; 732 } else { 733 dataArray[i][j] = outvalue; 734 } 735 } 736 } 737 } else { // using PersistentVector for data storage 738 if (pv == null) { 739 pv = new PersistentVector(); 740 pv.setFirstRow(6); 741 pv.setFieldDelimiter("#x20"); 742 } 743 String[] rowvals = new String[ncols]; 744 for (int j = 0; j < nrows; j++) { 745 double yloc = yllcorner + nrows * dely - j * dely; 746 for (int i = 0; i < ncols; i++) { 747 double xloc = xllcorner + i * delx; 748 if (shape.contains(xloc, yloc)) { 749 // inside the rectangle 750 rowvals[i] = invalueStr; 751 } else { 752 rowvals[i] = outvalueStr; 753 } 754 } 755 pv.addElement(rowvals); 756 rowvals = new String[ncols]; // needed to make sure new object 757 // added to pv 758 } 759 760 } 761 } 762 763 public static void main(String[] args) { 764 File testFile = new File("./test.asc"); 765 Grid grid = new Grid(testFile); 766 System.out.println("nrows: " + grid.nrows); 767 System.out.println("ncols: " + grid.ncols); 768 System.out.println("delx: " + grid.delx); 769 System.out.println("dely: " + grid.dely); 770 771 System.out.println("(0,0): " + grid.getValue(0, 0)); 772 System.out.println("(1,1): " + grid.getValue(1, 1)); 773 System.out.println("(2,2): " + grid.getValue(2, 2)); 774 System.out.println("(2.5,2.5): " 775 + grid.interpValue(2.5, 2.5, NEAREST_NEIGHBOR)); 776 System.out.println("(0.0,0.0): " 777 + grid.interpValue(0.0, 0.0, NEAREST_NEIGHBOR)); 778 779 System.out 780 .println("Starting to create an ASC file! ------------------"); 781 782 grid.createAsc("outtest.asc"); 783 System.out.println("Finished creating an ASC file! ------------------"); 784 785 System.out.println("Starting to rescale! ------------------"); 786 Grid newg = grid 787 .rescale(grid.nrows / 2, grid.ncols / 2, grid.delx * 2, 788 grid.dely * 2, grid.xllcorner, grid.yllcorner, 789 NEAREST_NEIGHBOR); 790 System.out.println("Finished rescaling! ------------------"); 791 // newg.createAsc("outtest2.asc"); 792 793 // String[] arr = (String[])grid.pv.elementAt(5); 794 795 // System.out.println("Str: "+arr[0]); 796 } 797 798 private Hashtable getHeaderInformation(BufferedReader br) { 799 Hashtable headerVals = new Hashtable(); 800 // unsure exactly how many header lines may occur 801 // but each line should have only two string tokens with the first being 802 // a name 803 // assume the 'name' is NOT a number 804 boolean eoh = false; // eoh -> end of header 805 while (!eoh) { 806 try { 807 cachedLine = br.readLine(); 808 } catch (Exception w) { 809 System.out 810 .println("error reading next line in getHeaderInformation!"); 811 eoh = true; 812 } 813 StringTokenizer st = new StringTokenizer(cachedLine); 814 int cnt = st.countTokens(); // should be only 2 815 if (cnt != 2) 816 eoh = true; 817 String firstToken = st.nextToken().trim(); 818 String secondToken = st.nextToken().trim(); 819 eoh = true; 820 try { 821 Double.parseDouble(firstToken); 822 } catch (Exception e) { 823 eoh = false; 824 } 825 if (!eoh) { 826 headerVals.put(firstToken, secondToken); 827 } 828 if (!headerVals.containsKey("NODATA_value")) { 829 headerVals.put("NODATA_value", "-9999"); // set a default 830 } 831 } 832 return headerVals; 833 } 834 835}