main.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332
  1. /*
  2. * r.in.xyz
  3. *
  4. * Calculates univariate statistics from the non-null cells of a GRASS raster map
  5. *
  6. * Copyright 2006-2014 by M. Hamish Bowman, and The GRASS Development Team
  7. * Author: M. Hamish Bowman, University of Otago, Dunedin, New Zealand
  8. *
  9. * Extended 2007 by Volker Wichmann to support the aggregate functions
  10. * median, percentile, skewness and trimmed mean
  11. *
  12. * This program is free software licensed under the GPL (>=v2).
  13. * Read the COPYING file that comes with GRASS for details.
  14. *
  15. * This program is intended as a replacement for the GRASS 5 s.cellstats module.
  16. */
  17. #include <grass/config.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <math.h>
  22. #include <sys/types.h>
  23. #include <grass/gis.h>
  24. #include <grass/raster.h>
  25. #include <grass/glocale.h>
  26. #include "local_proto.h"
  27. struct node
  28. {
  29. int next;
  30. double z;
  31. };
  32. #define SIZE_INCREMENT 10
  33. int num_nodes = 0;
  34. int max_nodes = 0;
  35. struct node *nodes;
  36. int new_node(void)
  37. {
  38. int n = num_nodes++;
  39. if (num_nodes >= max_nodes) {
  40. max_nodes += SIZE_INCREMENT;
  41. nodes = G_realloc(nodes, (size_t)max_nodes * sizeof(struct node));
  42. }
  43. return n;
  44. }
  45. /* add node to sorted, single linked list
  46. * returns id if head has to be saved to index array, otherwise -1 */
  47. int add_node(int head, double z)
  48. {
  49. int node_id, last_id, newnode_id, head_id;
  50. head_id = head;
  51. node_id = head_id;
  52. last_id = head_id;
  53. while (node_id != -1 && nodes[node_id].z < z) {
  54. last_id = node_id;
  55. node_id = nodes[node_id].next;
  56. }
  57. /* end of list, simply append */
  58. if (node_id == -1) {
  59. newnode_id = new_node();
  60. nodes[newnode_id].next = -1;
  61. nodes[newnode_id].z = z;
  62. nodes[last_id].next = newnode_id;
  63. return -1;
  64. }
  65. else if (node_id == head_id) { /* pole position, insert as head */
  66. newnode_id = new_node();
  67. nodes[newnode_id].next = head_id;
  68. head_id = newnode_id;
  69. nodes[newnode_id].z = z;
  70. return (head_id);
  71. }
  72. else { /* somewhere in the middle, insert */
  73. newnode_id = new_node();
  74. nodes[newnode_id].z = z;
  75. nodes[newnode_id].next = node_id;
  76. nodes[last_id].next = newnode_id;
  77. return -1;
  78. }
  79. }
  80. int main(int argc, char *argv[])
  81. {
  82. FILE *in_fp;
  83. int out_fd;
  84. char *infile, *outmap;
  85. int xcol, ycol, zcol, vcol, max_col, percent, skip_lines;
  86. int method = -1;
  87. int bin_n, bin_min, bin_max, bin_sum, bin_sumsq, bin_index;
  88. double zrange_min, zrange_max, vrange_min, vrange_max, d_tmp;
  89. char *fs; /* field delim */
  90. off_t filesize;
  91. int linesize;
  92. unsigned long estimated_lines, line;
  93. int from_stdin;
  94. int can_seek;
  95. RASTER_MAP_TYPE rtype;
  96. struct History history;
  97. char title[64];
  98. void *n_array, *min_array, *max_array, *sum_array, *sumsq_array,
  99. *index_array;
  100. void *raster_row, *ptr;
  101. struct Cell_head region;
  102. int rows, last_rows, row0, cols; /* scan box size */
  103. int row, col; /* counters */
  104. int pass, npasses;
  105. char buff[BUFFSIZE];
  106. double x, y, z;
  107. char **tokens;
  108. int ntokens; /* number of tokens */
  109. int arr_row, arr_col;
  110. unsigned long count, count_total;
  111. double min = 0.0 / 0.0; /* init as nan */
  112. double max = 0.0 / 0.0; /* init as nan */
  113. double zscale = 1.0;
  114. double vscale = 1.0;
  115. size_t offset, n_offset;
  116. int n = 0;
  117. double sum = 0.;
  118. double sumsq = 0.;
  119. double variance, mean, skew, sumdev;
  120. int pth = 0;
  121. double trim = 0.0;
  122. int j, k;
  123. int head_id, node_id;
  124. int r_low, r_up;
  125. struct GModule *module;
  126. struct Option *input_opt, *output_opt, *delim_opt, *percent_opt,
  127. *type_opt;
  128. struct Option *method_opt, *xcol_opt, *ycol_opt, *zcol_opt, *zrange_opt,
  129. *zscale_opt, *vcol_opt, *vrange_opt, *vscale_opt, *skip_opt;
  130. struct Option *trim_opt, *pth_opt;
  131. struct Flag *scan_flag, *shell_style, *skipline;
  132. G_gisinit(argv[0]);
  133. module = G_define_module();
  134. G_add_keyword(_("raster"));
  135. G_add_keyword(_("import"));
  136. G_add_keyword(_("statistics"));
  137. G_add_keyword(_("conversion"));
  138. G_add_keyword(_("aggregation"));
  139. G_add_keyword(_("binning"));
  140. G_add_keyword("ASCII");
  141. G_add_keyword(_("LIDAR"));
  142. module->description =
  143. _("Creates a raster map from an assemblage of many coordinates using univariate statistics.");
  144. input_opt = G_define_standard_option(G_OPT_F_BIN_INPUT);
  145. input_opt->description =
  146. _("ASCII file containing input data (or \"-\" to read from stdin)");
  147. output_opt = G_define_standard_option(G_OPT_R_OUTPUT);
  148. method_opt = G_define_option();
  149. method_opt->key = "method";
  150. method_opt->type = TYPE_STRING;
  151. method_opt->required = NO;
  152. method_opt->description = _("Statistic to use for raster values");
  153. method_opt->options =
  154. "n,min,max,range,sum,mean,stddev,variance,coeff_var,median,percentile,skewness,trimmean";
  155. method_opt->answer = "mean";
  156. method_opt->guisection = _("Statistic");
  157. G_asprintf((char **)&(method_opt->descriptions),
  158. "n;%s;"
  159. "min;%s;"
  160. "max;%s;"
  161. "range;%s;"
  162. "sum;%s;"
  163. "mean;%s;"
  164. "stddev;%s;"
  165. "variance;%s;"
  166. "coeff_var;%s;"
  167. "median;%s;"
  168. "percentile;%s;"
  169. "skewness;%s;"
  170. "trimmean;%s",
  171. _("Number of points in cell"),
  172. _("Minimum value of point values in cell"),
  173. _("Maximum value of point values in cell"),
  174. _("Range of point values in cell"),
  175. _("Sum of point values in cell"),
  176. _("Mean (average) value of point values in cell"),
  177. _("Standard deviation of point values in cell"),
  178. _("Variance of point values in cell"),
  179. _("Coefficient of variance of point values in cell"),
  180. _("Median value of point values in cell"),
  181. _("Pth (nth) percentile of point values in cell"),
  182. _("Skewness of point values in cell"),
  183. _("Trimmed mean of point values in cell"));
  184. delim_opt = G_define_standard_option(G_OPT_F_SEP);
  185. delim_opt->guisection = _("Input");
  186. xcol_opt = G_define_option();
  187. xcol_opt->key = "x";
  188. xcol_opt->type = TYPE_INTEGER;
  189. xcol_opt->required = NO;
  190. xcol_opt->answer = "1";
  191. xcol_opt->description =
  192. _("Column number of x coordinates in input file (first column is 1)");
  193. xcol_opt->guisection = _("Input");
  194. ycol_opt = G_define_option();
  195. ycol_opt->key = "y";
  196. ycol_opt->type = TYPE_INTEGER;
  197. ycol_opt->required = NO;
  198. ycol_opt->answer = "2";
  199. ycol_opt->description = _("Column number of y coordinates in input file");
  200. ycol_opt->guisection = _("Input");
  201. zcol_opt = G_define_option();
  202. zcol_opt->key = "z";
  203. zcol_opt->type = TYPE_INTEGER;
  204. zcol_opt->required = NO;
  205. zcol_opt->answer = "3";
  206. zcol_opt->label = _("Column number of data values in input file");
  207. zcol_opt->description =
  208. _("If a separate value column is given, this option refers to the "
  209. "z-coordinate column to be filtered by the zrange option");
  210. zcol_opt->guisection = _("Input");
  211. skip_opt = G_define_option();
  212. skip_opt->key = "skip";
  213. skip_opt->type = TYPE_INTEGER;
  214. skip_opt->required = NO;
  215. skip_opt->multiple = NO;
  216. skip_opt->answer = "0";
  217. skip_opt->description =
  218. _("Number of header lines to skip at top of input file");
  219. skip_opt->guisection = _("Input");
  220. zrange_opt = G_define_option();
  221. zrange_opt->key = "zrange";
  222. zrange_opt->type = TYPE_DOUBLE;
  223. zrange_opt->required = NO;
  224. zrange_opt->key_desc = "min,max";
  225. zrange_opt->description = _("Filter range for z data (min,max)");
  226. zrange_opt->guisection = _("Advanced Input");
  227. zscale_opt = G_define_option();
  228. zscale_opt->key = "zscale";
  229. zscale_opt->type = TYPE_DOUBLE;
  230. zscale_opt->required = NO;
  231. zscale_opt->answer = "1.0";
  232. zscale_opt->description = _("Scale to apply to z data");
  233. zscale_opt->guisection = _("Advanced Input");
  234. vcol_opt = G_define_option();
  235. vcol_opt->key = "value_column";
  236. vcol_opt->type = TYPE_INTEGER;
  237. vcol_opt->required = NO;
  238. vcol_opt->answer = "0";
  239. vcol_opt->label = _("Alternate column number of data values in input file");
  240. vcol_opt->description = _("If not given (or set to 0) the z-column data is used");
  241. vcol_opt->guisection = _("Advanced Input");
  242. vrange_opt = G_define_option();
  243. vrange_opt->key = "vrange";
  244. vrange_opt->type = TYPE_DOUBLE;
  245. vrange_opt->required = NO;
  246. vrange_opt->key_desc = "min,max";
  247. vrange_opt->description = _("Filter range for alternate value column data (min,max)");
  248. vrange_opt->guisection = _("Advanced Input");
  249. vscale_opt = G_define_option();
  250. vscale_opt->key = "vscale";
  251. vscale_opt->type = TYPE_DOUBLE;
  252. vscale_opt->required = NO;
  253. vscale_opt->answer = "1.0";
  254. vscale_opt->description = _("Scale to apply to alternate value column data");
  255. vscale_opt->guisection = _("Advanced Input");
  256. type_opt = G_define_standard_option(G_OPT_R_TYPE);
  257. type_opt->required = NO;
  258. type_opt->answer = "FCELL";
  259. type_opt->guisection = _("Output");
  260. percent_opt = G_define_option();
  261. percent_opt->key = "percent";
  262. percent_opt->type = TYPE_INTEGER;
  263. percent_opt->required = NO;
  264. percent_opt->answer = "100";
  265. percent_opt->options = "1-100";
  266. percent_opt->description = _("Percent of map to keep in memory");
  267. /* I would prefer to call the following "percentile", but that has too
  268. * much namespace overlap with the "percent" option above */
  269. pth_opt = G_define_option();
  270. pth_opt->key = "pth";
  271. pth_opt->type = TYPE_INTEGER;
  272. pth_opt->required = NO;
  273. pth_opt->options = "1-100";
  274. pth_opt->description = _("Pth percentile of the values");
  275. pth_opt->guisection = _("Statistic");
  276. trim_opt = G_define_option();
  277. trim_opt->key = "trim";
  278. trim_opt->type = TYPE_DOUBLE;
  279. trim_opt->required = NO;
  280. trim_opt->options = "0-50";
  281. trim_opt->description =
  282. _("Discard <trim> percent of the smallest and <trim> percent of the largest observations");
  283. trim_opt->guisection = _("Statistic");
  284. scan_flag = G_define_flag();
  285. scan_flag->key = 's';
  286. scan_flag->description = _("Scan data file for extent then exit");
  287. scan_flag->guisection = _("Scan");
  288. scan_flag->suppress_required = YES;
  289. shell_style = G_define_flag();
  290. shell_style->key = 'g';
  291. shell_style->description =
  292. _("In scan mode, print using shell script style");
  293. shell_style->guisection = _("Scan");
  294. shell_style->suppress_required = YES;
  295. skipline = G_define_flag();
  296. skipline->key = 'i';
  297. skipline->description = _("Ignore broken lines");
  298. G_option_required(output_opt, scan_flag, shell_style, NULL);
  299. G_option_requires(scan_flag, input_opt, NULL);
  300. G_option_requires(shell_style, input_opt, NULL);
  301. if (G_parser(argc, argv))
  302. exit(EXIT_FAILURE);
  303. /* parse input values */
  304. infile = input_opt->answer;
  305. outmap = output_opt->answer;
  306. if (shell_style->answer && !scan_flag->answer) {
  307. scan_flag->answer = 1; /* pointer not int, so set = shell_style->answer ? */
  308. }
  309. fs = G_option_to_separator(delim_opt);
  310. xcol = atoi(xcol_opt->answer);
  311. ycol = atoi(ycol_opt->answer);
  312. zcol = atoi(zcol_opt->answer);
  313. vcol = atoi(vcol_opt->answer);
  314. if ((xcol < 0) || (ycol < 0) || (zcol < 0) || (vcol < 0))
  315. G_fatal_error(_("Please specify a reasonable column number."));
  316. max_col = (xcol > ycol) ? xcol : ycol;
  317. max_col = (zcol > max_col) ? zcol : max_col;
  318. if(vcol)
  319. max_col = (vcol > max_col) ? vcol : max_col;
  320. percent = atoi(percent_opt->answer);
  321. zscale = atof(zscale_opt->answer);
  322. vscale = atof(vscale_opt->answer);
  323. skip_lines = atoi(skip_opt->answer);
  324. if (skip_lines < 0)
  325. G_fatal_error(_("Please specify reasonable number of lines to skip"));
  326. /* parse zrange and vrange */
  327. if (zrange_opt->answer != NULL) {
  328. if (zrange_opt->answers[0] == NULL)
  329. G_fatal_error(_("Invalid zrange"));
  330. sscanf(zrange_opt->answers[0], "%lf", &zrange_min);
  331. sscanf(zrange_opt->answers[1], "%lf", &zrange_max);
  332. if (zrange_min > zrange_max) {
  333. d_tmp = zrange_max;
  334. zrange_max = zrange_min;
  335. zrange_min = d_tmp;
  336. }
  337. }
  338. if (vrange_opt->answer != NULL) {
  339. if (vrange_opt->answers[0] == NULL)
  340. G_fatal_error(_("Invalid vrange"));
  341. sscanf(vrange_opt->answers[0], "%lf", &vrange_min);
  342. sscanf(vrange_opt->answers[1], "%lf", &vrange_max);
  343. if (vrange_min > vrange_max) {
  344. d_tmp = vrange_max;
  345. vrange_max = vrange_min;
  346. vrange_min = d_tmp;
  347. }
  348. }
  349. /* figure out what maps we need in memory */
  350. /* n n
  351. min min
  352. max max
  353. range min max max - min
  354. sum sum
  355. mean sum n sum/n
  356. stddev sum sumsq n sqrt((sumsq - sum*sum/n)/n)
  357. variance sum sumsq n (sumsq - sum*sum/n)/n
  358. coeff_var sum sumsq n sqrt((sumsq - sum*sum/n)/n) / (sum/n)
  359. median n array index to linked list
  360. percentile n array index to linked list
  361. skewness n array index to linked list
  362. trimmean n array index to linked list
  363. */
  364. bin_n = FALSE;
  365. bin_min = FALSE;
  366. bin_max = FALSE;
  367. bin_sum = FALSE;
  368. bin_sumsq = FALSE;
  369. bin_index = FALSE;
  370. if (strcmp(method_opt->answer, "n") == 0) {
  371. method = METHOD_N;
  372. bin_n = TRUE;
  373. }
  374. if (strcmp(method_opt->answer, "min") == 0) {
  375. method = METHOD_MIN;
  376. bin_min = TRUE;
  377. }
  378. if (strcmp(method_opt->answer, "max") == 0) {
  379. method = METHOD_MAX;
  380. bin_max = TRUE;
  381. }
  382. if (strcmp(method_opt->answer, "range") == 0) {
  383. method = METHOD_RANGE;
  384. bin_min = TRUE;
  385. bin_max = TRUE;
  386. }
  387. if (strcmp(method_opt->answer, "sum") == 0) {
  388. method = METHOD_SUM;
  389. bin_sum = TRUE;
  390. }
  391. if (strcmp(method_opt->answer, "mean") == 0) {
  392. method = METHOD_MEAN;
  393. bin_sum = TRUE;
  394. bin_n = TRUE;
  395. }
  396. if (strcmp(method_opt->answer, "stddev") == 0) {
  397. method = METHOD_STDDEV;
  398. bin_sum = TRUE;
  399. bin_sumsq = TRUE;
  400. bin_n = TRUE;
  401. }
  402. if (strcmp(method_opt->answer, "variance") == 0) {
  403. method = METHOD_VARIANCE;
  404. bin_sum = TRUE;
  405. bin_sumsq = TRUE;
  406. bin_n = TRUE;
  407. }
  408. if (strcmp(method_opt->answer, "coeff_var") == 0) {
  409. method = METHOD_COEFF_VAR;
  410. bin_sum = TRUE;
  411. bin_sumsq = TRUE;
  412. bin_n = TRUE;
  413. }
  414. if (strcmp(method_opt->answer, "median") == 0) {
  415. method = METHOD_MEDIAN;
  416. bin_index = TRUE;
  417. }
  418. if (strcmp(method_opt->answer, "percentile") == 0) {
  419. if (pth_opt->answer != NULL)
  420. pth = atoi(pth_opt->answer);
  421. else
  422. G_fatal_error(_("Unable to calculate percentile without the pth option specified!"));
  423. method = METHOD_PERCENTILE;
  424. bin_index = TRUE;
  425. }
  426. if (strcmp(method_opt->answer, "skewness") == 0) {
  427. method = METHOD_SKEWNESS;
  428. bin_index = TRUE;
  429. }
  430. if (strcmp(method_opt->answer, "trimmean") == 0) {
  431. if (trim_opt->answer != NULL)
  432. trim = atof(trim_opt->answer) / 100.0;
  433. else
  434. G_fatal_error(_("Unable to calculate trimmed mean without the trim option specified!"));
  435. method = METHOD_TRIMMEAN;
  436. bin_index = TRUE;
  437. }
  438. if (strcmp("CELL", type_opt->answer) == 0)
  439. rtype = CELL_TYPE;
  440. else if (strcmp("DCELL", type_opt->answer) == 0)
  441. rtype = DCELL_TYPE;
  442. else
  443. rtype = FCELL_TYPE;
  444. if (method == METHOD_N)
  445. rtype = CELL_TYPE;
  446. G_get_window(&region);
  447. rows = last_rows = region.rows;
  448. npasses = 1;
  449. if (percent < 100) {
  450. rows = (int)(region.rows * (percent / 100.0));
  451. npasses = region.rows / rows;
  452. last_rows = region.rows - npasses * rows;
  453. if (last_rows)
  454. npasses++;
  455. else
  456. last_rows = rows;
  457. }
  458. cols = region.cols;
  459. G_debug(2, "region.n=%f region.s=%f region.ns_res=%f", region.north,
  460. region.south, region.ns_res);
  461. G_debug(2, "region.rows=%d [box_rows=%d] region.cols=%d", region.rows,
  462. rows, region.cols);
  463. if (!scan_flag->answer) {
  464. /* check if rows * (cols + 1) go into a size_t */
  465. if (sizeof(size_t) < 8) {
  466. double dsize = rows * (cols + 1);
  467. if (dsize != (size_t)rows * (cols + 1))
  468. G_fatal_error(_("Unable to process the hole map at once. "
  469. "Please set the %s option to some value lower than 100."),
  470. percent_opt->key);
  471. }
  472. /* allocate memory (test for enough before we start) */
  473. if (bin_n)
  474. n_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(CELL_TYPE));
  475. if (bin_min)
  476. min_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(rtype));
  477. if (bin_max)
  478. max_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(rtype));
  479. if (bin_sum)
  480. sum_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(rtype));
  481. if (bin_sumsq)
  482. sumsq_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(rtype));
  483. if (bin_index)
  484. index_array =
  485. G_calloc((size_t)rows * (cols + 1), Rast_cell_size(CELL_TYPE));
  486. /* and then free it again */
  487. if (bin_n)
  488. G_free(n_array);
  489. if (bin_min)
  490. G_free(min_array);
  491. if (bin_max)
  492. G_free(max_array);
  493. if (bin_sum)
  494. G_free(sum_array);
  495. if (bin_sumsq)
  496. G_free(sumsq_array);
  497. if (bin_index)
  498. G_free(index_array);
  499. /** end memory test **/
  500. }
  501. /* open input file */
  502. if (strcmp("-", infile) == 0) {
  503. from_stdin = TRUE;
  504. in_fp = stdin;
  505. infile = G_store("stdin"); /* filename for history metadata */
  506. }
  507. else {
  508. from_stdin = FALSE;
  509. if ((in_fp = fopen(infile, "r")) == NULL)
  510. G_fatal_error(_("Unable to open input file <%s>"), infile);
  511. }
  512. can_seek = fseek(in_fp, 0L, SEEK_SET) == 0;
  513. /* can't rewind() non-files */
  514. if (!can_seek && npasses != 1) {
  515. G_warning(_("If input is not from a file it is only possible to perform a single pass."));
  516. npasses = 1;
  517. }
  518. /* skip past header lines */
  519. for (line = 0; line < (unsigned long)skip_lines; line++) {
  520. if (0 == G_getl2(buff, BUFFSIZE - 1, in_fp))
  521. break;
  522. }
  523. if (scan_flag->answer) {
  524. if (zrange_opt->answer || vrange_opt->answer)
  525. G_warning(_("Range filters will not be taken into account during scan"));
  526. scan_bounds(in_fp, xcol, ycol, zcol, vcol, fs, shell_style->answer,
  527. skipline->answer, zscale, vscale);
  528. /* close input file */
  529. if (!from_stdin)
  530. fclose(in_fp);
  531. exit(EXIT_SUCCESS);
  532. }
  533. /* open output map */
  534. out_fd = Rast_open_new(outmap, rtype);
  535. if (can_seek) {
  536. /* guess at number of lines in the file without actually reading it all in */
  537. for (line = 0; line < 10; line++) { /* arbitrarily use 10th line for guess */
  538. if (0 == G_getl2(buff, BUFFSIZE - 1, in_fp))
  539. break;
  540. linesize = strlen(buff) + 1;
  541. }
  542. G_fseek(in_fp, 0L, SEEK_END);
  543. filesize = G_ftell(in_fp);
  544. rewind(in_fp);
  545. if (linesize < 6) /* min possible: "0,0,0\n" */
  546. linesize = 6;
  547. estimated_lines = filesize / linesize;
  548. G_debug(2, "estimated number of lines in file: %lu", estimated_lines);
  549. }
  550. else
  551. estimated_lines = -1;
  552. /* allocate memory for a single row of output data */
  553. raster_row = Rast_allocate_buf(rtype);
  554. G_message(_("Reading input data..."));
  555. count_total = 0;
  556. /* main binning loop(s) */
  557. for (pass = 1; pass <= npasses; pass++) {
  558. if (npasses > 1)
  559. G_message(_("Pass #%d (of %d) ..."), pass, npasses);
  560. if (can_seek) {
  561. rewind(in_fp);
  562. /* skip past header lines again */
  563. for (line = 0; line < (unsigned long)skip_lines; line++) {
  564. if (0 == G_getl2(buff, BUFFSIZE - 1, in_fp))
  565. break;
  566. }
  567. }
  568. /* figure out segmentation */
  569. row0 = (pass - 1) * rows;
  570. if (pass == npasses) {
  571. rows = last_rows;
  572. }
  573. G_debug(2, "pass=%d/%d rows=%d", pass, npasses, rows);
  574. if (bin_n) {
  575. G_debug(2, "allocating n_array");
  576. n_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(CELL_TYPE));
  577. blank_array(n_array, rows, cols, CELL_TYPE, 0);
  578. }
  579. if (bin_min) {
  580. G_debug(2, "allocating min_array");
  581. min_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(rtype));
  582. blank_array(min_array, rows, cols, rtype, -1); /* fill with NULLs */
  583. }
  584. if (bin_max) {
  585. G_debug(2, "allocating max_array");
  586. max_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(rtype));
  587. blank_array(max_array, rows, cols, rtype, -1); /* fill with NULLs */
  588. }
  589. if (bin_sum) {
  590. G_debug(2, "allocating sum_array");
  591. sum_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(rtype));
  592. blank_array(sum_array, rows, cols, rtype, 0);
  593. }
  594. if (bin_sumsq) {
  595. G_debug(2, "allocating sumsq_array");
  596. sumsq_array = G_calloc((size_t)rows * (cols + 1), Rast_cell_size(rtype));
  597. blank_array(sumsq_array, rows, cols, rtype, 0);
  598. }
  599. if (bin_index) {
  600. G_debug(2, "allocating index_array");
  601. index_array =
  602. G_calloc((size_t)rows * (cols + 1), Rast_cell_size(CELL_TYPE));
  603. blank_array(index_array, rows, cols, CELL_TYPE, -1); /* fill with NULLs */
  604. }
  605. line = 0;
  606. count = 0;
  607. G_percent_reset();
  608. while (0 != G_getl2(buff, BUFFSIZE - 1, in_fp)) {
  609. line++;
  610. if (line % 100000 == 0) { /* mod for speed */
  611. if (!can_seek)
  612. G_clicker();
  613. else if (line < estimated_lines)
  614. G_percent(line, estimated_lines, 3);
  615. }
  616. if ((buff[0] == '#') || (buff[0] == '\0')) {
  617. continue; /* line is a comment or blank */
  618. }
  619. G_chop(buff); /* remove leading and trailing whitespace from the string. unneded?? */
  620. tokens = G_tokenize(buff, fs);
  621. ntokens = G_number_of_tokens(tokens);
  622. if ((ntokens < 3) || (max_col > ntokens)) {
  623. if (skipline->answer) {
  624. G_warning(_("Not enough data columns. "
  625. "Incorrect delimiter or column number? "
  626. "Found the following character(s) in row %lu:\n[%s]"),
  627. line, buff);
  628. G_warning(_("Line ignored as requested"));
  629. continue; /* line is garbage */
  630. }
  631. else {
  632. G_fatal_error(_("Not enough data columns. "
  633. "Incorrect delimiter or column number? "
  634. "Found the following character(s) in row %lu:\n[%s]"),
  635. line, buff);
  636. }
  637. }
  638. /* too slow?
  639. if ( G_projection() == PROJECTION_LL ) {
  640. G_scan_easting( tokens[xcol-1], &x, region.proj);
  641. G_scan_northing( tokens[ycol-1], &y, region.proj);
  642. }
  643. else {
  644. */
  645. if (1 != sscanf(tokens[ycol - 1], "%lf", &y))
  646. G_fatal_error(_("Bad y-coordinate line %lu column %d. <%s>"),
  647. line, ycol, tokens[ycol - 1]);
  648. if (y <= region.south || y > region.north) {
  649. G_free_tokens(tokens);
  650. continue;
  651. }
  652. if (1 != sscanf(tokens[xcol - 1], "%lf", &x))
  653. G_fatal_error(_("Bad x-coordinate line %lu column %d. <%s>"),
  654. line, xcol, tokens[xcol - 1]);
  655. if (x < region.west || x >= region.east) {
  656. G_free_tokens(tokens);
  657. continue;
  658. }
  659. /* find the bin in the current array box */
  660. arr_row = (int)((region.north - y) / region.ns_res) - row0;
  661. if (arr_row < 0 || arr_row >= rows) {
  662. G_free_tokens(tokens);
  663. continue;
  664. }
  665. arr_col = (int)((x - region.west) / region.ew_res);
  666. /* G_debug(5, "arr_row: %d arr_col: %d", arr_row, arr_col); */
  667. if (1 != sscanf(tokens[zcol - 1], "%lf", &z))
  668. G_fatal_error(_("Bad z-coordinate line %lu column %d. <%s>"),
  669. line, zcol, tokens[zcol - 1]);
  670. z = z * zscale;
  671. if (zrange_opt->answer) {
  672. if (z < zrange_min || z > zrange_max) {
  673. G_free_tokens(tokens);
  674. continue;
  675. }
  676. }
  677. if(vcol) {
  678. if (1 != sscanf(tokens[vcol - 1], "%lf", &z))
  679. G_fatal_error(_("Bad data value line %lu column %d. <%s>"),
  680. line, vcol, tokens[vcol - 1]);
  681. /* we're past the zrange check, so pass over control of the variable */
  682. z = z * vscale;
  683. if (vrange_opt->answer) {
  684. if (z < vrange_min || z > vrange_max) {
  685. G_free_tokens(tokens);
  686. continue;
  687. }
  688. }
  689. }
  690. count++;
  691. /* G_debug(5, "x: %f, y: %f, z: %f", x, y, z); */
  692. G_free_tokens(tokens);
  693. if (bin_n)
  694. update_n(n_array, cols, arr_row, arr_col);
  695. if (bin_min)
  696. update_min(min_array, cols, arr_row, arr_col, rtype, z);
  697. if (bin_max)
  698. update_max(max_array, cols, arr_row, arr_col, rtype, z);
  699. if (bin_sum)
  700. update_sum(sum_array, cols, arr_row, arr_col, rtype, z);
  701. if (bin_sumsq)
  702. update_sumsq(sumsq_array, cols, arr_row, arr_col, rtype, z);
  703. if (bin_index) {
  704. ptr = index_array;
  705. ptr =
  706. G_incr_void_ptr(ptr,
  707. ((arr_row * cols) +
  708. arr_col) * Rast_cell_size(CELL_TYPE));
  709. if (Rast_is_null_value(ptr, CELL_TYPE)) { /* first node */
  710. head_id = new_node();
  711. nodes[head_id].next = -1;
  712. nodes[head_id].z = z;
  713. Rast_set_c_value(ptr, head_id, CELL_TYPE); /* store index to head */
  714. }
  715. else { /* head is already there */
  716. head_id = Rast_get_c_value(ptr, CELL_TYPE); /* get index to head */
  717. head_id = add_node(head_id, z);
  718. if (head_id != -1)
  719. Rast_set_c_value(ptr, head_id, CELL_TYPE); /* store index to head */
  720. }
  721. }
  722. } /* while !EOF */
  723. G_percent(1, 1, 1); /* flush */
  724. G_debug(2, "pass %d finished, %lu coordinates in box", pass, count);
  725. count_total += count;
  726. G_message(_("%lu points found in input file"), line);
  727. /* calc stats and output */
  728. G_message(_("Writing to output raster map..."));
  729. for (row = 0; row < rows; row++) {
  730. switch (method) {
  731. case METHOD_N: /* n is a straight copy */
  732. Rast_raster_cpy(raster_row,
  733. n_array +
  734. (row * cols * Rast_cell_size(CELL_TYPE)), cols,
  735. CELL_TYPE);
  736. break;
  737. case METHOD_MIN:
  738. Rast_raster_cpy(raster_row,
  739. min_array + (row * cols * Rast_cell_size(rtype)),
  740. cols, rtype);
  741. break;
  742. case METHOD_MAX:
  743. Rast_raster_cpy(raster_row,
  744. max_array + (row * cols * Rast_cell_size(rtype)),
  745. cols, rtype);
  746. break;
  747. case METHOD_SUM:
  748. Rast_raster_cpy(raster_row,
  749. sum_array + (row * cols * Rast_cell_size(rtype)),
  750. cols, rtype);
  751. break;
  752. case METHOD_RANGE: /* (max-min) */
  753. ptr = raster_row;
  754. for (col = 0; col < cols; col++) {
  755. offset = (row * cols + col) * Rast_cell_size(rtype);
  756. min = Rast_get_d_value(min_array + offset, rtype);
  757. max = Rast_get_d_value(max_array + offset, rtype);
  758. Rast_set_d_value(ptr, max - min, rtype);
  759. ptr = G_incr_void_ptr(ptr, Rast_cell_size(rtype));
  760. }
  761. break;
  762. case METHOD_MEAN: /* (sum / n) */
  763. ptr = raster_row;
  764. for (col = 0; col < cols; col++) {
  765. offset = (row * cols + col) * Rast_cell_size(rtype);
  766. n_offset = (row * cols + col) * Rast_cell_size(CELL_TYPE);
  767. n = Rast_get_c_value(n_array + n_offset, CELL_TYPE);
  768. sum = Rast_get_d_value(sum_array + offset, rtype);
  769. if (n == 0)
  770. Rast_set_null_value(ptr, 1, rtype);
  771. else
  772. Rast_set_d_value(ptr, (sum / n), rtype);
  773. ptr = G_incr_void_ptr(ptr, Rast_cell_size(rtype));
  774. }
  775. break;
  776. case METHOD_STDDEV: /* sqrt(variance) */
  777. case METHOD_VARIANCE: /* (sumsq - sum*sum/n)/n */
  778. case METHOD_COEFF_VAR: /* 100 * stdev / mean */
  779. ptr = raster_row;
  780. for (col = 0; col < cols; col++) {
  781. offset = (row * cols + col) * Rast_cell_size(rtype);
  782. n_offset = (row * cols + col) * Rast_cell_size(CELL_TYPE);
  783. n = Rast_get_c_value(n_array + n_offset, CELL_TYPE);
  784. sum = Rast_get_d_value(sum_array + offset, rtype);
  785. sumsq = Rast_get_d_value(sumsq_array + offset, rtype);
  786. if (n == 0)
  787. Rast_set_null_value(ptr, 1, rtype);
  788. else {
  789. variance = (sumsq - sum * sum / n) / n;
  790. if (variance < GRASS_EPSILON)
  791. variance = 0.0;
  792. if (method == METHOD_STDDEV)
  793. Rast_set_d_value(ptr, sqrt(variance), rtype);
  794. else if (method == METHOD_VARIANCE)
  795. Rast_set_d_value(ptr, variance, rtype);
  796. else if (method == METHOD_COEFF_VAR)
  797. Rast_set_d_value(ptr,
  798. 100 * sqrt(variance) / (sum /
  799. n),
  800. rtype);
  801. }
  802. ptr = G_incr_void_ptr(ptr, Rast_cell_size(rtype));
  803. }
  804. break;
  805. case METHOD_MEDIAN: /* median, if only one point in cell we will use that */
  806. ptr = raster_row;
  807. for (col = 0; col < cols; col++) {
  808. n_offset = (row * cols + col) * Rast_cell_size(CELL_TYPE);
  809. if (Rast_is_null_value(index_array + n_offset, CELL_TYPE)) /* no points in cell */
  810. Rast_set_null_value(ptr, 1, rtype);
  811. else { /* one or more points in cell */
  812. head_id =
  813. Rast_get_c_value(index_array + n_offset,
  814. CELL_TYPE);
  815. node_id = head_id;
  816. n = 0;
  817. while (node_id != -1) { /* count number of points in cell */
  818. n++;
  819. node_id = nodes[node_id].next;
  820. }
  821. if (n == 1) /* only one point, use that */
  822. Rast_set_d_value(ptr, nodes[head_id].z,
  823. rtype);
  824. else if (n % 2 != 0) { /* odd number of points: median_i = (n + 1) / 2 */
  825. n = (n + 1) / 2;
  826. node_id = head_id;
  827. for (j = 1; j < n; j++) /* get "median element" */
  828. node_id = nodes[node_id].next;
  829. Rast_set_d_value(ptr, nodes[node_id].z,
  830. rtype);
  831. }
  832. else { /* even number of points: median = (val_below + val_above) / 2 */
  833. z = (n + 1) / 2.0;
  834. n = floor(z);
  835. node_id = head_id;
  836. for (j = 1; j < n; j++) /* get element "below" */
  837. node_id = nodes[node_id].next;
  838. z = (nodes[node_id].z +
  839. nodes[nodes[node_id].next].z) / 2;
  840. Rast_set_d_value(ptr, z, rtype);
  841. }
  842. }
  843. ptr = G_incr_void_ptr(ptr, Rast_cell_size(rtype));
  844. }
  845. break;
  846. case METHOD_PERCENTILE: /* rank = (pth*(n+1))/100; interpolate linearly */
  847. ptr = raster_row;
  848. for (col = 0; col < cols; col++) {
  849. n_offset = (row * cols + col) * Rast_cell_size(CELL_TYPE);
  850. if (Rast_is_null_value(index_array + n_offset, CELL_TYPE)) /* no points in cell */
  851. Rast_set_null_value(ptr, 1, rtype);
  852. else {
  853. head_id =
  854. Rast_get_c_value(index_array + n_offset,
  855. CELL_TYPE);
  856. node_id = head_id;
  857. n = 0;
  858. while (node_id != -1) { /* count number of points in cell */
  859. n++;
  860. node_id = nodes[node_id].next;
  861. }
  862. z = (pth * (n + 1)) / 100.0;
  863. r_low = floor(z); /* lower rank */
  864. if (r_low < 1)
  865. r_low = 1;
  866. else if (r_low > n)
  867. r_low = n;
  868. r_up = ceil(z); /* upper rank */
  869. if (r_up > n)
  870. r_up = n;
  871. node_id = head_id;
  872. for (j = 1; j < r_low; j++) /* search lower value */
  873. node_id = nodes[node_id].next;
  874. z = nodes[node_id].z; /* save lower value */
  875. node_id = head_id;
  876. for (j = 1; j < r_up; j++) /* search upper value */
  877. node_id = nodes[node_id].next;
  878. z = (z + nodes[node_id].z) / 2;
  879. Rast_set_d_value(ptr, z, rtype);
  880. }
  881. ptr = G_incr_void_ptr(ptr, Rast_cell_size(rtype));
  882. }
  883. break;
  884. case METHOD_SKEWNESS: /* skewness = sum(xi-mean)^3/(N-1)*s^3 */
  885. ptr = raster_row;
  886. for (col = 0; col < cols; col++) {
  887. n_offset = (row * cols + col) * Rast_cell_size(CELL_TYPE);
  888. if (Rast_is_null_value(index_array + n_offset, CELL_TYPE)) /* no points in cell */
  889. Rast_set_null_value(ptr, 1, rtype);
  890. else {
  891. head_id =
  892. Rast_get_c_value(index_array + n_offset,
  893. CELL_TYPE);
  894. node_id = head_id;
  895. n = 0; /* count */
  896. sum = 0.0; /* sum */
  897. sumsq = 0.0; /* sum of squares */
  898. sumdev = 0.0; /* sum of (xi - mean)^3 */
  899. skew = 0.0; /* skewness */
  900. while (node_id != -1) {
  901. z = nodes[node_id].z;
  902. n++;
  903. sum += z;
  904. sumsq += (z * z);
  905. node_id = nodes[node_id].next;
  906. }
  907. if (n > 1) { /* if n == 1, skew is "0.0" */
  908. mean = sum / n;
  909. node_id = head_id;
  910. while (node_id != -1) {
  911. z = nodes[node_id].z;
  912. sumdev += pow((z - mean), 3);
  913. node_id = nodes[node_id].next;
  914. }
  915. variance = (sumsq - sum * sum / n) / n;
  916. if (variance < GRASS_EPSILON)
  917. skew = 0.0;
  918. else
  919. skew =
  920. sumdev / ((n - 1) *
  921. pow(sqrt(variance), 3));
  922. }
  923. Rast_set_d_value(ptr, skew, rtype);
  924. }
  925. ptr = G_incr_void_ptr(ptr, Rast_cell_size(rtype));
  926. }
  927. break;
  928. case METHOD_TRIMMEAN:
  929. ptr = raster_row;
  930. for (col = 0; col < cols; col++) {
  931. n_offset = (row * cols + col) * Rast_cell_size(CELL_TYPE);
  932. if (Rast_is_null_value(index_array + n_offset, CELL_TYPE)) /* no points in cell */
  933. Rast_set_null_value(ptr, 1, rtype);
  934. else {
  935. head_id =
  936. Rast_get_c_value(index_array + n_offset,
  937. CELL_TYPE);
  938. node_id = head_id;
  939. n = 0;
  940. while (node_id != -1) { /* count number of points in cell */
  941. n++;
  942. node_id = nodes[node_id].next;
  943. }
  944. if (1 == n)
  945. mean = nodes[head_id].z;
  946. else {
  947. k = floor(trim * n + 0.5); /* number of ranks to discard on each tail */
  948. if (k > 0 && (n - 2 * k) > 0) { /* enough elements to discard */
  949. node_id = head_id;
  950. for (j = 0; j < k; j++) /* move to first rank to consider */
  951. node_id = nodes[node_id].next;
  952. j = k + 1;
  953. k = n - k;
  954. n = 0;
  955. sum = 0.0;
  956. while (j <= k) { /* get values in interval */
  957. n++;
  958. sum += nodes[node_id].z;
  959. node_id = nodes[node_id].next;
  960. j++;
  961. }
  962. }
  963. else {
  964. node_id = head_id;
  965. n = 0;
  966. sum = 0.0;
  967. while (node_id != -1) {
  968. n++;
  969. sum += nodes[node_id].z;
  970. node_id = nodes[node_id].next;
  971. }
  972. }
  973. mean = sum / n;
  974. }
  975. Rast_set_d_value(ptr, mean, rtype);
  976. }
  977. ptr = G_incr_void_ptr(ptr, Rast_cell_size(rtype));
  978. }
  979. break;
  980. default:
  981. G_fatal_error("?");
  982. }
  983. G_percent(row, rows, 5);
  984. /* write out line of raster data */
  985. Rast_put_row(out_fd, raster_row, rtype);
  986. }
  987. /* free memory */
  988. if (bin_n)
  989. G_free(n_array);
  990. if (bin_min)
  991. G_free(min_array);
  992. if (bin_max)
  993. G_free(max_array);
  994. if (bin_sum)
  995. G_free(sum_array);
  996. if (bin_sumsq)
  997. G_free(sumsq_array);
  998. if (bin_index) {
  999. G_free(index_array);
  1000. G_free(nodes);
  1001. num_nodes = 0;
  1002. max_nodes = 0;
  1003. nodes = NULL;
  1004. }
  1005. } /* passes loop */
  1006. G_percent(1, 1, 1); /* flush */
  1007. G_free(raster_row);
  1008. /* close input file */
  1009. if (!from_stdin)
  1010. fclose(in_fp);
  1011. /* close raster file & write history */
  1012. Rast_close(out_fd);
  1013. sprintf(title, "Raw x,y,z data binned into a raster grid by cell %s",
  1014. method_opt->answer);
  1015. Rast_put_cell_title(outmap, title);
  1016. Rast_short_history(outmap, "raster", &history);
  1017. Rast_command_history(&history);
  1018. Rast_set_history(&history, HIST_DATSRC_1, infile);
  1019. Rast_write_history(outmap, &history);
  1020. G_done_msg(_("%lu points found in region."), count_total);
  1021. exit(EXIT_SUCCESS);
  1022. }
  1023. int scan_bounds(FILE * fp, int xcol, int ycol, int zcol, int vcol, char *fs,
  1024. int shell_style, int skipline, double zscale, double vscale)
  1025. {
  1026. unsigned long line;
  1027. int first, max_col;
  1028. char buff[BUFFSIZE];
  1029. double min_x, max_x, min_y, max_y, min_z, max_z, min_v, max_v;
  1030. char **tokens;
  1031. int ntokens; /* number of tokens */
  1032. double x, y, z, v;
  1033. max_col = (xcol > ycol) ? xcol : ycol;
  1034. max_col = (zcol > max_col) ? zcol : max_col;
  1035. if(vcol)
  1036. max_col = (vcol > max_col) ? vcol : max_col;
  1037. line = 0;
  1038. first = TRUE;
  1039. G_verbose_message(_("Scanning data ..."));
  1040. while (0 != G_getl2(buff, BUFFSIZE - 1, fp)) {
  1041. line++;
  1042. if ((buff[0] == '#') || (buff[0] == '\0')) {
  1043. continue; /* line is a comment or blank */
  1044. }
  1045. G_chop(buff); /* remove leading and trailing whitespace. unneded?? */
  1046. tokens = G_tokenize(buff, fs);
  1047. ntokens = G_number_of_tokens(tokens);
  1048. if ((ntokens < 3) || (max_col > ntokens)) {
  1049. if (skipline) {
  1050. G_warning(_("Not enough data columns. "
  1051. "Incorrect delimiter or column number? "
  1052. "Found the following character(s) in row %lu:\n[%s]"),
  1053. line, buff);
  1054. G_warning(_("Line ignored as requested"));
  1055. continue; /* line is garbage */
  1056. }
  1057. else {
  1058. G_fatal_error(_("Not enough data columns. "
  1059. "Incorrect delimiter or column number? "
  1060. "Found the following character(s) in row %lu:\n[%s]"),
  1061. line, buff);
  1062. }
  1063. }
  1064. /* too slow?
  1065. if ( G_projection() == PROJECTION_LL ) {
  1066. G_scan_easting( tokens[xcol-1], &x, region.proj);
  1067. G_scan_northing( tokens[ycol-1], &y, region.proj);
  1068. }
  1069. else {
  1070. */
  1071. if (1 != sscanf(tokens[xcol - 1], "%lf", &x))
  1072. G_fatal_error(_("Bad x-coordinate line %lu column %d. <%s>"), line,
  1073. xcol, tokens[xcol - 1]);
  1074. if (first) {
  1075. min_x = x;
  1076. max_x = x;
  1077. }
  1078. else {
  1079. if (x < min_x)
  1080. min_x = x;
  1081. if (x > max_x)
  1082. max_x = x;
  1083. }
  1084. if (1 != sscanf(tokens[ycol - 1], "%lf", &y))
  1085. G_fatal_error(_("Bad y-coordinate line %lu column %d. <%s>"), line,
  1086. ycol, tokens[ycol - 1]);
  1087. if (first) {
  1088. min_y = y;
  1089. max_y = y;
  1090. }
  1091. else {
  1092. if (y < min_y)
  1093. min_y = y;
  1094. if (y > max_y)
  1095. max_y = y;
  1096. }
  1097. if (1 != sscanf(tokens[zcol - 1], "%lf", &z))
  1098. G_fatal_error(_("Bad z-coordinate line %lu column %d. <%s>"), line,
  1099. zcol, tokens[zcol - 1]);
  1100. if (first) {
  1101. min_z = z;
  1102. max_z = z;
  1103. if(!vcol)
  1104. first = FALSE;
  1105. }
  1106. else {
  1107. if (z < min_z)
  1108. min_z = z;
  1109. if (z > max_z)
  1110. max_z = z;
  1111. }
  1112. if(vcol) {
  1113. if (1 != sscanf(tokens[vcol - 1], "%lf", &v))
  1114. G_fatal_error(_("Bad data value line %lu column %d. <%s>"), line,
  1115. vcol, tokens[vcol - 1]);
  1116. if (first) {
  1117. min_v = v;
  1118. max_v = v;
  1119. first = FALSE;
  1120. }
  1121. else {
  1122. if (v < min_v)
  1123. min_v = v;
  1124. if (v > max_v)
  1125. max_v = v;
  1126. }
  1127. }
  1128. G_free_tokens(tokens);
  1129. }
  1130. if (!shell_style) {
  1131. fprintf(stderr, _("Range: min max\n"));
  1132. fprintf(stdout, "x: %11.15g %11.15g\n", min_x, max_x);
  1133. fprintf(stdout, "y: %11.15g %11.15g\n", min_y, max_y);
  1134. fprintf(stdout, "z: %11.15g %11.15g\n", min_z * zscale, max_z * zscale);
  1135. if(vcol)
  1136. fprintf(stdout, "v: %11.15g %11.15g\n", min_v * vscale, max_v * vscale);
  1137. }
  1138. else {
  1139. fprintf(stdout, "n=%.15g s=%.15g e=%.15g w=%.15g b=%.15g t=%.15g",
  1140. max_y, min_y, max_x, min_x, min_z * zscale, max_z * zscale);
  1141. if(vcol)
  1142. fprintf(stdout, " min=%.15g max=%.15g\n", min_v * vscale,
  1143. max_v * vscale);
  1144. else
  1145. fprintf(stdout, "\n");
  1146. }
  1147. G_debug(1, "Processed %lu lines.", line);
  1148. G_debug(1, "region template: g.region n=%.15g s=%.15g e=%.15g w=%.15g",
  1149. max_y, min_y, max_x, min_x);
  1150. return 0;
  1151. }