COMMENTS 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. From: Glynn Clements <glynn.clements@virgin.net>
  2. Date: Tue, 5 Mar 2002 16:44:33 +0000
  3. To: Markus Neteler <neteler@itc.it>
  4. Subject: Re: Question on raster programming
  5. Markus Neteler wrote:
  6. > may I ask you for some assistance for a simple example on
  7. > GRASS raster programming?
  8. > I would like to have r.example as reference for raster
  9. > programming. The module will do nothing exciting but show
  10. > how to deal with the different precisions.
  11. >
  12. > the line in question is the inner col-loop, where I
  13. > copy the cell values from the old to the new map.
  14. > It does not compile due to the variable definition.
  15. >
  16. > In old modules I have seen ugly things to deal with
  17. > INT, FCELL and DCELL (lots of cases etc). Probably it
  18. > is much more simple using the
  19. >
  20. > void *inrast;
  21. >
  22. > definition on top. But then, I don't understand to access
  23. > it... Yes, programming newbie question. Perhaps you have the
  24. > patience to help me. I have several older modules in the queue
  25. > which I would like to release after an update. Before hacking
  26. > in lots of case statements, I prefer to learn the up-to-date
  27. > method.
  28. If you want to handle multiple data types, you generally[1] have to
  29. use a switch statement.
  30. [1] If you are only copying values, you can use other methods (e.g.
  31. memcpy), but if you wish to actually process the cell values, they
  32. need to be stored in a variable of the appropriate type.
  33. Suppose you wanted the equivalent of:
  34. r.mapcalc 'out = f(in)'
  35. The main loop would look something like:
  36. extern CELL f_c(CELL);
  37. extern FCELL f_f(FCELL);
  38. extern DCELL f_d(DCELL);
  39. ...
  40. for (col=0; col < ncols; col++)
  41. {
  42. CELL c;
  43. FCELL f;
  44. DCELL d;
  45. switch (data_type)
  46. {
  47. case CELL_TYPE:
  48. c = ((CELL *) inrast)[col];
  49. c = f_c(c);
  50. ((CELL *) outrast)[col] = c;
  51. break;
  52. case FCELL_TYPE:
  53. f = ((FCELL *) inrast)[col];
  54. f = f_f(f);
  55. ((FCELL *) outrast)[col] = f;
  56. break;
  57. case DCELL_TYPE:
  58. d = ((DCELL *) inrast)[col];
  59. d = f_d(d);
  60. ((DCELL *) outrast)[col] = d;
  61. break;
  62. }
  63. }
  64. In the most extreme case, you might have nested switch statements to
  65. deal with all of the different combinations of input/output types.
  66. If it isn't important that the operation is done at the map's native
  67. precision, a simpler approach is to just use DCELL values and let the
  68. G_{get,put}_*_row functions handle the conversion, e.g.
  69. DCELL f_d(DCELL x)
  70. {
  71. /* some function */
  72. return x;
  73. }
  74. extern DCELL f_d(DCELL);
  75. ...
  76. DCELL *inrast = G_allocate_d_raster_buf();
  77. DCELL *outrast = G_allocate_d_raster_buf();
  78. for (row = 0; row < nrows; row++)
  79. {
  80. if (G_get_d_raster_row (infd, inrast, row) < 0)
  81. G_fatal_error(...);
  82. for (col=0; col < ncols; col++)
  83. outrast[col] = f_d(inrast[col]);
  84. if (G_put_d_raster_row (outfd, outrast) < 0)
  85. G_fatal_error(...);
  86. }
  87. One other comment about the example: it isn't necessary to use
  88. sprintf() to format error messages; G_fatal_error() takes a format
  89. string and arguments, e.g.
  90. G_fatal_error("cell file [%s] not found", name);
  91. --
  92. Glynn Clements <glynn.clements@virgin.net>
  93. From: Glynn Clements <glynn.clements@virgin.net>
  94. Date: Thu, 7 Mar 2002 16:51:43 +0000
  95. To: Markus Neteler <neteler@itc.it>
  96. Subject: Re: Question on raster programming
  97. Markus Neteler wrote:
  98. > What do you think about the macro method implemented in
  99. > r.sunmask (src/raster/r.sunmask/)? Is that a good
  100. > or possibly slowing down the module for FCELL and DCELL
  101. > (in fact it's incredible slow, just for INT DEMs it is acceptable).
  102. In the case of r.sunmask, the raster_value() macro/function is
  103. pointless. The data is always converted to DCELL before being used;
  104. the code should just allocate DCELL buffers and read the data with
  105. G_get_d_raster_row().
  106. As for speed, I wouldn't have thought that type-handling logic would
  107. be significant compared to the amount of work that's done in the
  108. various G_get_*_row() functions.
  109. Most code should probably just work with DCELL values, and let libgis
  110. perform the conversions, unless the code is only applicable to CELL
  111. values, or it handles CELL values differently.
  112. --
  113. Glynn Clements <glynn.clements@virgin.net>
  114. Markus Neteler wrote:
  115. > sorry to bother you again. I am now continuing to write
  116. > r.example (which just copies a file) to have an example
  117. > on raster programming. Maybe you recall our conversation on
  118. > that some time ago (find it attached as well).
  119. >
  120. > A remaining question is how to define this:
  121. >
  122. > extern CELL f_c(CELL);
  123. > extern FCELL f_f(FCELL);
  124. > extern DCELL f_d(DCELL);
  125. >
  126. > f_c, f_f, f_d
  127. >
  128. > Sorry for this question, but I am clueless here.
  129. For copying a file, these would just be identity functions, e.g.
  130. CELL f_c(CELL x)
  131. {
  132. return x;
  133. }
  134. Actually, there aren't many things which you could do within that
  135. framework. For most practical applications, a cell in the output map
  136. would depend upon more than just the corresponding cell in a single
  137. input map. You would typically have multiple input maps, and/or use
  138. the values of multiple cells in computing the value of each output
  139. cell.
  140. Some other points:
  141. 1. Copying input parameters into a buffer, i.e.:
  142. strcpy (name, option.input->answer);
  143. strcpy (result, option.output->answer);
  144. is usually unnecessary. Furthermore, it's something which should be
  145. discouraged, due to the usual problems with fixed-size buffers.
  146. 2. Pre-formatting error/warning messages, e.g.:
  147. if (mapset == NULL)
  148. {
  149. char buf[200];
  150. sprintf (buf, "cell file [%s] not found", name);
  151. G_fatal_error (buf);
  152. }
  153. is unnecessary, as G_fatal_error() and G_warning() already do this,
  154. e.g.
  155. if (!mapset)
  156. G_fatal_error("cell file [%s] not found", name);
  157. 3. Ideally, all abnormal exits would be via G_fatal_error(), rather
  158. than calling exit() directly.
  159. 4. The value passed to exit() should be non-negative. exit(-1) is just
  160. a confusing way of writing exit(255).
  161. --
  162. Glynn Clements <glynn.clements@virgin.net>