main.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*-
  2. * s.sample - GRASS program to sample a raster map at site locations.
  3. * Copyright (C) 1994. James Darrell McCauley.
  4. *
  5. * Author: James Darrell McCauley darrell@mccauley-usa.com
  6. * http://mccauley-usa.com/
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. *
  22. * Modification History:
  23. * <04 Jan 1994> - began coding (jdm)
  24. * <06 Jan 1994> - announced version 0.1B on pasture.ecn.purdue.edu (jdm)
  25. * <21 Jan 1994> - changed wording on help screen. Revised to 0.2B (jdm)
  26. * <24 Jan 1994> - got rid of diagnostic messages. Revised to 0.3B (jdm)
  27. * ?? Revised to 0.4B (jdm)
  28. * <19 Dec 1994> - fixed bug in readsites, added html. Revised to 0.5B (jdm)
  29. * <02 Jan 1995> - cleaned Gmakefile, man page, html.
  30. * fixed memory error in bilinear and cubic 0.6B (jdm)
  31. * <25 Feb 1995> - cleaned 'gcc -Wall' warnings 0.7B (jdm)
  32. * <15 Jun 1995> - fixed pointer error for G_{col,row}_to_{easting,northing}.
  33. * 0.8B (jdm)
  34. * <13 Sep 2000> - released under GPL
  35. *
  36. */
  37. /* s.sample v 0.8B <15 Jun 1995>; Copyright (c) 1994-1995. James Darrell McCauley" */
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <math.h>
  42. #include <grass/gis.h>
  43. #include <grass/glocale.h>
  44. #include <grass/dbmi.h>
  45. #include <grass/Vect.h>
  46. int main(int argc, char **argv)
  47. {
  48. char *mapset;
  49. double scale, predicted, actual;
  50. INTERP_TYPE method = UNKNOWN;
  51. int fdrast; /* file descriptor for raster map is int */
  52. struct Cell_head window;
  53. struct GModule *module;
  54. struct Map_info In, Out;
  55. struct
  56. {
  57. struct Option *input, *output, *rast, *z, *column;
  58. } parm;
  59. struct
  60. {
  61. struct Flag *B, *C;
  62. } flag;
  63. int line, nlines;
  64. struct line_pnts *Points;
  65. struct line_cats *Cats;
  66. /* Attributes */
  67. int field, nrecords;
  68. int ctype;
  69. struct field_info *Fi;
  70. dbDriver *Driver;
  71. dbCatValArray cvarr;
  72. char buf[2000];
  73. dbString sql;
  74. G_gisinit(argv[0]);
  75. module = G_define_module();
  76. module->keywords = _("vector");
  77. module->description =
  78. _("Samples a raster map at vector point locations.");
  79. parm.input = G_define_standard_option(G_OPT_V_INPUT);
  80. parm.input->description = _("Vector map defining sample points");
  81. parm.column = G_define_option();
  82. parm.column->key = "column";
  83. parm.column->type = TYPE_STRING;
  84. parm.column->required = YES;
  85. parm.column->description =
  86. _("Vector map attribute column to use for comparison");
  87. parm.output = G_define_standard_option(G_OPT_V_OUTPUT);
  88. parm.output->description = _("Vector map to store differences");
  89. parm.rast = G_define_standard_option(G_OPT_R_INPUT);
  90. parm.rast->key = "raster";
  91. parm.rast->description = _("Raster map to be sampled");
  92. parm.z = G_define_option();
  93. parm.z->key = "z";
  94. parm.z->type = TYPE_DOUBLE;
  95. parm.z->required = NO;
  96. parm.z->answer = "1.0";
  97. parm.z->description =
  98. _("Option scaling factor for values read from raster map. "
  99. "Sampled values will be multiplied by this factor");
  100. flag.B = G_define_flag();
  101. flag.B->key = 'b';
  102. flag.B->description =
  103. _("Bilinear interpolation (default is nearest neighbor)");
  104. flag.C = G_define_flag();
  105. flag.C->key = 'c';
  106. flag.C->description =
  107. _("Cubic convolution interpolation (default is nearest neighbor)");
  108. if (G_parser(argc, argv))
  109. exit(EXIT_FAILURE);
  110. sscanf(parm.z->answer, "%lf", &scale);
  111. if (flag.B->answer || flag.C->answer) {
  112. if (flag.C->answer)
  113. method = CUBIC;
  114. if (flag.B->answer)
  115. method = BILINEAR;
  116. if (flag.B->answer && flag.C->answer)
  117. G_fatal_error(_("Flags -b & -c are mutually exclusive. Choose only one."));
  118. }
  119. else {
  120. method = NEAREST;
  121. }
  122. G_get_window(&window);
  123. /* Open input */
  124. if ((mapset = G_find_vector2(parm.input->answer, "")) == NULL)
  125. G_fatal_error(_("Vector map <%s> not found"), parm.input->answer);
  126. Vect_set_open_level(2);
  127. Vect_open_old(&In, parm.input->answer, mapset);
  128. if ((mapset = G_find_cell2(parm.rast->answer, "")) == NULL)
  129. G_fatal_error(_("Raster map <%s> not found"), parm.rast->answer);
  130. if ((fdrast = G_open_cell_old(parm.rast->answer, mapset)) < 0)
  131. G_fatal_error(_("Unable to open raster map <%s>"), parm.rast->answer);
  132. /* Read attributes */
  133. field = 1;
  134. Fi = Vect_get_field(&In, field);
  135. if (Fi == NULL)
  136. G_fatal_error(_("Database connection not defined for layer %d"),
  137. field);
  138. Driver = db_start_driver_open_database(Fi->driver, Fi->database);
  139. if (Driver == NULL)
  140. G_fatal_error("Unable to open database <%s> by driver <%s>",
  141. Fi->database, Fi->driver);
  142. nrecords = db_select_CatValArray(Driver, Fi->table, Fi->key,
  143. parm.column->answer, NULL, &cvarr);
  144. G_debug(3, "nrecords = %d", nrecords);
  145. ctype = cvarr.ctype;
  146. if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE)
  147. G_fatal_error(_("Column type <%s> not supported (must be integer or double precision)"),
  148. db_sqltype_name(ctype));
  149. if (nrecords < 0)
  150. G_fatal_error(_("Unable to select data from table"));
  151. G_message(_("%d records selected from table"), nrecords);
  152. db_close_database_shutdown_driver(Driver);
  153. /* Open output */
  154. Vect_open_new(&Out, parm.output->answer, 0);
  155. Vect_hist_copy(&In, &Out);
  156. Vect_hist_command(&Out);
  157. /* Create table */
  158. db_init_string(&sql);
  159. Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
  160. Vect_map_add_dblink(&Out, Fi->number, Fi->name, Fi->table, Fi->key,
  161. Fi->database, Fi->driver);
  162. Driver =
  163. db_start_driver_open_database(Fi->driver,
  164. Vect_subst_var(Fi->database, &Out));
  165. if (Driver == NULL)
  166. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  167. Fi->database, Fi->driver);
  168. sprintf(buf,
  169. "create table %s ( cat integer, pnt_val double precision, rast_val double precision, "
  170. "diff double precision)", Fi->table);
  171. db_set_string(&sql, buf);
  172. if (db_execute_immediate(Driver, &sql) != DB_OK)
  173. G_fatal_error(_("Unable to create table <%s>"), db_get_string(&sql));
  174. if (db_create_index2(Driver, Fi->table, Fi->key) != DB_OK)
  175. G_warning(_("Cannot create index"));
  176. if (db_grant_on_table
  177. (Driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
  178. G_fatal_error(_("Unable to grant privileges on table <%s>"),
  179. Fi->table);
  180. G_message(_("Checking vector points..."));
  181. Points = Vect_new_line_struct();
  182. Cats = Vect_new_cats_struct();
  183. nlines = Vect_get_num_lines(&In);
  184. for (line = 1; line <= nlines; line++) {
  185. int type, cat, ret, cval;
  186. double dval;
  187. G_debug(3, "line = %d", line);
  188. type = Vect_read_line(&In, Points, Cats, line);
  189. if (!(type & GV_POINT))
  190. continue;
  191. Vect_cat_get(Cats, 1, &cat);
  192. G_debug(4, "cat = %d", cat);
  193. /* find actual value */
  194. if (ctype == DB_C_TYPE_INT) {
  195. ret = db_CatValArray_get_value_int(&cvarr, cat, &cval);
  196. if (ret != DB_OK)
  197. G_warning(_("No record for category %d in table <%s>"), cat,
  198. Fi->table);
  199. actual = cval;
  200. }
  201. else if (ctype == DB_C_TYPE_DOUBLE) {
  202. ret = db_CatValArray_get_value_double(&cvarr, cat, &dval);
  203. if (ret != DB_OK)
  204. G_warning(_("No record for category %d in table <%s>"), cat,
  205. Fi->table);
  206. actual = dval;
  207. }
  208. else {
  209. G_fatal_error(_("Column type not supported"));
  210. }
  211. G_debug(4, "actual = %e", actual);
  212. /* find predicted value */
  213. predicted =
  214. scale * G_get_raster_sample(fdrast, &window, NULL, Points->y[0],
  215. Points->x[0], 0, method);
  216. G_debug(4, "predicted = %e", predicted);
  217. Vect_reset_cats(Cats);
  218. Vect_cat_set(Cats, 1, cat);
  219. sprintf(buf, "insert into %s values ( %d, %e, %e, %e )",
  220. Fi->table, cat, actual, predicted, predicted - actual);
  221. db_set_string(&sql, buf);
  222. if (db_execute_immediate(Driver, &sql) != DB_OK)
  223. G_fatal_error(_("Unable to insert row: %s"), db_get_string(&sql));
  224. Vect_write_line(&Out, GV_POINT, Points, Cats);
  225. }
  226. db_close_database_shutdown_driver(Driver);
  227. G_close_cell(fdrast);
  228. Vect_close(&In);
  229. Vect_build(&Out, stderr);
  230. Vect_close(&Out);
  231. exit(EXIT_SUCCESS);
  232. }