123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- From: Glynn Clements <glynn.clements@virgin.net>
- Date: Tue, 5 Mar 2002 16:44:33 +0000
- To: Markus Neteler <neteler@itc.it>
- Subject: Re: Question on raster programming
- Markus Neteler wrote:
- > may I ask you for some assistance for a simple example on
- > GRASS raster programming?
- > I would like to have r.example as reference for raster
- > programming. The module will do nothing exciting but show
- > how to deal with the different precisions.
- >
- > the line in question is the inner col-loop, where I
- > copy the cell values from the old to the new map.
- > It does not compile due to the variable definition.
- >
- > In old modules I have seen ugly things to deal with
- > INT, FCELL and DCELL (lots of cases etc). Probably it
- > is much more simple using the
- >
- > void *inrast;
- >
- > definition on top. But then, I don't understand to access
- > it... Yes, programming newbie question. Perhaps you have the
- > patience to help me. I have several older modules in the queue
- > which I would like to release after an update. Before hacking
- > in lots of case statements, I prefer to learn the up-to-date
- > method.
- If you want to handle multiple data types, you generally[1] have to
- use a switch statement.
- [1] If you are only copying values, you can use other methods (e.g.
- memcpy), but if you wish to actually process the cell values, they
- need to be stored in a variable of the appropriate type.
- Suppose you wanted the equivalent of:
- r.mapcalc 'out = f(in)'
- The main loop would look something like:
- extern CELL f_c(CELL);
- extern FCELL f_f(FCELL);
- extern DCELL f_d(DCELL);
- ...
- for (col=0; col < ncols; col++)
- {
- CELL c;
- FCELL f;
- DCELL d;
- switch (data_type)
- {
- case CELL_TYPE:
- c = ((CELL *) inrast)[col];
- c = f_c(c);
- ((CELL *) outrast)[col] = c;
- break;
- case FCELL_TYPE:
- f = ((FCELL *) inrast)[col];
- f = f_f(f);
- ((FCELL *) outrast)[col] = f;
- break;
- case DCELL_TYPE:
- d = ((DCELL *) inrast)[col];
- d = f_d(d);
- ((DCELL *) outrast)[col] = d;
- break;
- }
- }
- In the most extreme case, you might have nested switch statements to
- deal with all of the different combinations of input/output types.
- If it isn't important that the operation is done at the map's native
- precision, a simpler approach is to just use DCELL values and let the
- G_{get,put}_*_row functions handle the conversion, e.g.
- DCELL f_d(DCELL x)
- {
- /* some function */
- return x;
- }
- extern DCELL f_d(DCELL);
- ...
- DCELL *inrast = G_allocate_d_raster_buf();
- DCELL *outrast = G_allocate_d_raster_buf();
- for (row = 0; row < nrows; row++)
- {
- if (G_get_d_raster_row (infd, inrast, row) < 0)
- G_fatal_error(...);
-
- for (col=0; col < ncols; col++)
- outrast[col] = f_d(inrast[col]);
- if (G_put_d_raster_row (outfd, outrast) < 0)
- G_fatal_error(...);
- }
- One other comment about the example: it isn't necessary to use
- sprintf() to format error messages; G_fatal_error() takes a format
- string and arguments, e.g.
- G_fatal_error("cell file [%s] not found", name);
- --
- Glynn Clements <glynn.clements@virgin.net>
- From: Glynn Clements <glynn.clements@virgin.net>
- Date: Thu, 7 Mar 2002 16:51:43 +0000
- To: Markus Neteler <neteler@itc.it>
- Subject: Re: Question on raster programming
- Markus Neteler wrote:
- > What do you think about the macro method implemented in
- > r.sunmask (src/raster/r.sunmask/)? Is that a good
- > or possibly slowing down the module for FCELL and DCELL
- > (in fact it's incredible slow, just for INT DEMs it is acceptable).
- In the case of r.sunmask, the raster_value() macro/function is
- pointless. The data is always converted to DCELL before being used;
- the code should just allocate DCELL buffers and read the data with
- G_get_d_raster_row().
- As for speed, I wouldn't have thought that type-handling logic would
- be significant compared to the amount of work that's done in the
- various G_get_*_row() functions.
- Most code should probably just work with DCELL values, and let libgis
- perform the conversions, unless the code is only applicable to CELL
- values, or it handles CELL values differently.
- --
- Glynn Clements <glynn.clements@virgin.net>
- Markus Neteler wrote:
- > sorry to bother you again. I am now continuing to write
- > r.example (which just copies a file) to have an example
- > on raster programming. Maybe you recall our conversation on
- > that some time ago (find it attached as well).
- >
- > A remaining question is how to define this:
- >
- > extern CELL f_c(CELL);
- > extern FCELL f_f(FCELL);
- > extern DCELL f_d(DCELL);
- >
- > f_c, f_f, f_d
- >
- > Sorry for this question, but I am clueless here.
- For copying a file, these would just be identity functions, e.g.
- CELL f_c(CELL x)
- {
- return x;
- }
- Actually, there aren't many things which you could do within that
- framework. For most practical applications, a cell in the output map
- would depend upon more than just the corresponding cell in a single
- input map. You would typically have multiple input maps, and/or use
- the values of multiple cells in computing the value of each output
- cell.
- Some other points:
- 1. Copying input parameters into a buffer, i.e.:
- strcpy (name, option.input->answer);
- strcpy (result, option.output->answer);
- is usually unnecessary. Furthermore, it's something which should be
- discouraged, due to the usual problems with fixed-size buffers.
- 2. Pre-formatting error/warning messages, e.g.:
- if (mapset == NULL)
- {
- char buf[200];
- sprintf (buf, "cell file [%s] not found", name);
- G_fatal_error (buf);
- }
- is unnecessary, as G_fatal_error() and G_warning() already do this,
- e.g.
- if (!mapset)
- G_fatal_error("cell file [%s] not found", name);
- 3. Ideally, all abnormal exits would be via G_fatal_error(), rather
- than calling exit() directly.
- 4. The value passed to exit() should be non-negative. exit(-1) is just
- a confusing way of writing exit(255).
- --
- Glynn Clements <glynn.clements@virgin.net>
|