prt_report.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <grass/raster.h>
  4. #include "global.h"
  5. int print_report(int unit1, int unit2)
  6. {
  7. int ns, nl, nx;
  8. char num[100];
  9. int len, new;
  10. CELL *cats, *prev;
  11. int first;
  12. int i;
  13. int divider_level;
  14. int after_header;
  15. int need_format;
  16. int with_stats;
  17. char *cp;
  18. int spacing;
  19. char dot;
  20. /* examine units, determine output format */
  21. for (i = unit1; i <= unit2; i++) {
  22. need_format = 1;
  23. unit[i].label[0] = "";
  24. unit[i].label[1] = "";
  25. switch (unit[i].type) {
  26. case CELL_COUNTS:
  27. need_format = 0;
  28. unit[i].len = 5;
  29. unit[i].label[0] = " cell";
  30. unit[i].label[1] = "count";
  31. ns = 0;
  32. sprintf(num, "%ld", count_sum(&ns, -1));
  33. len = strlen(num);
  34. if (len > unit[i].len)
  35. unit[i].len = len;
  36. break;
  37. case PERCENT_COVER:
  38. need_format = 0;
  39. unit[i].dp = 2;
  40. unit[i].len = 6;
  41. unit[i].label[0] = " % ";
  42. unit[i].label[1] = "cover";
  43. unit[i].eformat = 0;
  44. break;
  45. case SQ_METERS:
  46. unit[i].label[0] = "square";
  47. unit[i].label[1] = "meters";
  48. unit[i].factor = 1.0;
  49. break;
  50. case SQ_KILOMETERS:
  51. unit[i].label[0] = " square ";
  52. unit[i].label[1] = "kilometers";
  53. unit[i].factor = 1.0e-6;
  54. break;
  55. case ACRES:
  56. unit[i].label[0] = "";
  57. unit[i].label[1] = "acres";
  58. unit[i].factor = 2.47105381467165e-4; /* 640 acres in a sq mile */
  59. break;
  60. case HECTARES:
  61. unit[i].label[0] = "";
  62. unit[i].label[1] = "hectares";
  63. unit[i].factor = 1.0e-4;
  64. break;
  65. case SQ_MILES:
  66. unit[i].label[0] = "square";
  67. unit[i].label[1] = " miles";
  68. unit[i].factor = 3.86102158542446e-7; /* 1 / ( (0.0254m/in * 12in/ft * 5280ft/mi)^2 ) */
  69. break;
  70. default:
  71. G_fatal_error("Unit %d not yet supported", unit[i].type);
  72. }
  73. if (need_format) {
  74. unit[i].dp = 6;
  75. unit[i].len = 10;
  76. unit[i].eformat = 0;
  77. ns = 0;
  78. format_parms(area_sum(&ns, -1) * unit[i].factor,
  79. &unit[i].len, &unit[i].dp, &(unit[i].eformat),
  80. e_format);
  81. }
  82. }
  83. /* figure out how big the category numbers are when printed */
  84. for (nl = 0; nl < nlayers; nl++)
  85. layers[nl].nlen = 0;
  86. for (ns = 0; ns < nstats; ns++) {
  87. cats = Gstats[ns].cats;
  88. for (nl = 0; nl < nlayers; nl++) {
  89. construct_val_str(nl, &cats[nl], num);
  90. len = strlen(num);
  91. if (len > layers[nl].nlen)
  92. layers[nl].nlen = len;
  93. }
  94. }
  95. /* compute maximum category description lengths */
  96. len = page_width - 2;
  97. for (i = unit1; i <= unit2; i++)
  98. len -= (unit[i].len + 1);
  99. for (nl = 0; nl < nlayers; nl++) {
  100. len -= (layers[nl].nlen + 1);
  101. layers[nl].clen = len;
  102. }
  103. /* print the report */
  104. header(unit1, unit2);
  105. after_header = 1;
  106. new = 1;
  107. divider_level = -1;
  108. for (ns = 0; ns < nstats; ns++) {
  109. int NS;
  110. cats = Gstats[ns].cats;
  111. /* determine the number of lines needed to print the cat labels
  112. * by pretending to print the labels and counting the number of
  113. * print calls needed
  114. */
  115. if (page_length > 0) {
  116. i = 0;
  117. for (nl = 0; nl < nlayers; nl++) {
  118. cp = construct_cat_label(nl, cats[nl]);
  119. while (cp) {
  120. i++;
  121. cp = print_label(cp, layers[nl].clen, 0, 0, ' ');
  122. }
  123. }
  124. if (nunits)
  125. i += nlayers; /* divider lines */
  126. /* if we don't have enough lines, go to a new page */
  127. if (nlines <= i + 2) {
  128. trailer();
  129. header(unit1, unit2);
  130. after_header = 1;
  131. new = 2;
  132. }
  133. }
  134. /* print the report */
  135. for (nl = 0; nl < nlayers; nl++) {
  136. if (new || (prev[nl] != cats[nl])) {
  137. /* divider line between layers */
  138. if (nunits && divider_level != nl && !after_header) {
  139. for (nx = 0; nx < nl; nx++)
  140. fprintf(stdout, "|%*s", layers[nx].nlen, "");
  141. fprintf(stdout, "|");
  142. for (nx = layers[nl].clen + layers[nx].nlen + 1; nx > 0;
  143. nx--)
  144. fprintf(stdout, "-");
  145. for (i = unit1; i <= unit2; i++) {
  146. fprintf(stdout, "|");
  147. for (nx = unit[i].len; nx > 0; nx--)
  148. fprintf(stdout, "-");
  149. }
  150. fprintf(stdout, "|");
  151. newline();
  152. }
  153. divider_level = nl;
  154. after_header = 0;
  155. first = 1;
  156. if (!new)
  157. new = 1;
  158. cp = construct_cat_label(nl, cats[nl]);
  159. while (cp) {
  160. for (nx = 0; nx < nl; nx++)
  161. fprintf(stdout, "|%*s", layers[nx].nlen, "");
  162. if (first) {
  163. construct_val_str(nl, &cats[nl], num);
  164. fprintf(stdout, "|%*s|", layers[nl].nlen, num);
  165. }
  166. else
  167. fprintf(stdout, "|%*s|", layers[nl].nlen, "");
  168. with_stats = nunits && first;
  169. /*
  170. if (new == 2 && nl != nlayers-1)
  171. with_stats = 0;
  172. */
  173. if (with_stats)
  174. /* if it's not the lowest level of the table */
  175. {
  176. if (nl != nlayers - 1) {
  177. if (new != 2)
  178. NS = ns; /* to memorise total */
  179. /* if new is 2 then the total for this class should be reprinted on the
  180. top of the page. So we need to remember ns of total in case we need to
  181. print it again later */
  182. spacing = 0;
  183. dot = '_';
  184. }
  185. else {
  186. spacing = 2;
  187. dot = '.';
  188. }
  189. }
  190. else {
  191. spacing = 0;
  192. dot = ' ';
  193. }
  194. cp = print_label(cp, layers[nl].clen, 1, spacing, dot);
  195. if (with_stats) {
  196. for (i = unit1; i <= unit2; i++)
  197. if (nl != nlayers - 1)
  198. print_unit(i, NS, nl);
  199. else
  200. print_unit(i, ns, nl);
  201. }
  202. else {
  203. for (i = unit1; i <= unit2; i++)
  204. fprintf(stdout, "|%*s", unit[i].len, "");
  205. }
  206. fprintf(stdout, "|");
  207. newline();
  208. first = 0;
  209. }
  210. }
  211. }
  212. new = 0;
  213. prev = cats;
  214. }
  215. /* overall totals */
  216. if (nunits) {
  217. divider("|");
  218. print_label("|TOTAL", layers[0].nlen + layers[0].clen + 2, 1, 0, ' ');
  219. for (i = unit1; i <= unit2; i++)
  220. print_unit(i, 0, -1);
  221. /*
  222. print_unit(i,-1,-1);
  223. */
  224. fprintf(stdout, "|");
  225. newline();
  226. }
  227. trailer();
  228. return 0;
  229. }
  230. int construct_val_str(int nl, CELL * pval, char *str)
  231. {
  232. char str1[50], str2[50];
  233. char *descr;
  234. DCELL dLow, dHigh;
  235. if (Rast_is_c_null_value(pval))
  236. sprintf(str, "%s", no_data_str);
  237. else if (!is_fp[nl] || as_int)
  238. sprintf(str, "%d", *pval);
  239. else { /* find out which floating point range to print */
  240. if (cat_ranges)
  241. descr = Rast_get_ith_d_cat(&layers[nl].labels, *pval,
  242. &dLow, &dHigh);
  243. else {
  244. dLow = (DMAX[nl] - DMIN[nl]) / nsteps *
  245. (double)(*pval - 1) + DMIN[nl];
  246. dHigh = (DMAX[nl] - DMIN[nl]) / nsteps * (double)*pval + DMIN[nl];
  247. }
  248. sprintf(str1, "%10f", dLow);
  249. sprintf(str2, "%10f", dHigh);
  250. G_strip(str1);
  251. G_strip(str2);
  252. G_trim_decimal(str1);
  253. G_trim_decimal(str2);
  254. sprintf(str, "%s-%s", str1, str2);
  255. }
  256. return 0;
  257. }
  258. char *construct_cat_label(int nl, CELL cat)
  259. {
  260. DCELL dLow, dHigh;
  261. CELL tmp = cat;
  262. static char str[500];
  263. if (!is_fp[nl] || as_int)
  264. return Rast_get_c_cat(&cat, &layers[nl].labels);
  265. else { /* find or construct the label for
  266. floating point range to print */
  267. if (Rast_is_c_null_value(&tmp))
  268. return G_store("no data");
  269. if (cat_ranges)
  270. return Rast_get_ith_d_cat(&layers[nl].labels, cat,
  271. &dLow, &dHigh);
  272. else {
  273. dLow = (DMAX[nl] - DMIN[nl]) / (double)nsteps *
  274. (double)(cat - 1) + DMIN[nl];
  275. dHigh = (DMAX[nl] - DMIN[nl]) / (double)nsteps *
  276. (double)cat + DMIN[nl];
  277. sprintf(str, "from %s to %s",
  278. Rast_get_d_cat(&dLow, &layers[nl].labels),
  279. Rast_get_d_cat(&dHigh, &layers[nl].labels));
  280. return str;
  281. }
  282. } /* fp label */
  283. return 0;
  284. }