Assignment: Reading and multiplying an ascii grid

Develop code in C/C++ to read a grid in ascii format whose name is specified by the user on the command line, multiply it by a number also given by the user on the command line, and print it out, like this:
[ltoma@dover:\~] multgrid test1.asc  3
This will read the grid named set1.asc, multiply it by 3, and print it out. Note that the header of the grid stays the same, and NODATA values, if any, should stay as NODATA.
[ltoma@dover:\~] multgrid test1.asc 3
reading grid test1.asc
ncols         10 
nrows         10
xllcorner     271845
yllcorner     3875415
cellsize      30
NODATA_value  -9999
3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3

Grid ascii format

One of the formats for grid data is the so called arc-ascii format. It stores the data in text (ascii) form. This is not the most efficient format, but it's nice to be able to see the values in the grid, so we'll use it.

The first 6 lines in an arc-ascii file represent the header of the terrain; it stores the number of rows in the grid, the number of columns, the geographical coordinates of the lower left corner, the spacing in the grid (assumed to be the same both horizontally and vertically), and a nodata value (this is the value that is used for points where the elevation could not be measured).

ncols         391
nrows         472
xllcorner     271845
yllcorner     3875415
cellsize      30
NODATA_value  -9999
Following the header there are nrows lines, each line containing ncols values, for a total of nrows * ncols values. These values represent the elevations sampled from the terrain. Thus, a grid terrain is basically a 2D-array of elevation values. You can assume that the elevations are integers (though you can also use floats or doubles if you want). The dimensions of the grid can be found out from the header. The other information stored in the header (xllcorner, yllcorner, cellsize, NODATA_value) you will happily ignore for this lab since we won't care about geographical coordinates---- but you have to read them anyways in order to get to the point in the file where you can start reading the elevations. The NODATA value is the elevation value assigned to points whose elevation is unknown. So a NODATA value in the elevation grid means "unknown".

To store all the information of a grid use a struct:

typedef struct _grid {

     int  rows, cols;  // the size of the grid
     ....
     float** data;   //the 2D array of value in the grid 

} Grid;

Test grids

Test grid sare available here. Play with the small grids before you try the larger ones.

General outline

Your program should have a main() function that takes the name of the grid on the command line, calls a function that reads the grid in memory, and calls a function that multiplies the grid.

Define a structure to hold the grid header and data, call it Grid (ideally, defined in file Grid.h). I imagine the main() function will look something like this:

int main(char** args, int argc) {


      char *gridfname; 
      float m; 
     //check args and argc to make sure the user entered a  file
     //name and a value on the command line

     Grid grid; 
     / * read the elevation grid from file into this
     structure. Note that first you have to read the number of rows
     and columns, then you have to allocate the 2D-array in the grid,
     then you have to fill it with values from the file
     */
    readGridfromFile(gridfname, & grid); 

    printGrid(grid); 

    multiply(grid, m); 
    /* multiply the data in the grid by m */

    printGrid(grid); 
}

Reading a grid from a file

You'll need to write code that reads a grid from a file. One thing you will need to figure out is how to work with files in C or C++. Below is a piece of code that opens a file and reads an integer.
FILE* f; char s[100]; int nrows;

f=fopen("myfile.asc", "r");
if (f== NULL) {
   printf("cannot open file..");
   exit(1);
}

fscanf(f, "%s", s);
printf("read %s from file\n", s);
fscanf(f, "%d", &nrows);
printf("read %d from file\n", nrows);

Testing your grid reader

To test that you read the right values, write a printGrid (Grid g) method that prints the grid (header and values); it should print the same information as when you open the grid.asc file. You may want to break this function into two: printHeader and printValues.

In addition to the printGrid() method, write a printInfo (Grid g) method that prints the important information about the grid: rows, cols, h_min and h_max.

See some test grids at the top of this page. Some of them (europe.asc) are large, so better not open them in a browser. While testing, you should try getting the small ones to work before you try any of the larger ones.

Submitting your work

Make a folder called multgrid in your svn folder on microwave, and copy all your files there.

Enjoy!