1 #include <math.h>
2 #include <grass/dbmi.h>
3 #include <grass/glocale.h>
4 #include "global.h"
5
report(void)6 int report(void)
7 {
8 int i;
9 char left[20], right[20];
10
11 if (!options.print && !(options.option == O_COUNT ||
12 options.option == O_LENGTH ||
13 options.option == O_AREA)) {
14 G_warning(_("No totals for selected option"));
15 return 0;
16 }
17
18 switch (options.option) {
19 case O_CAT:
20 if (G_verbose() > G_verbose_min())
21 fprintf(stdout, "cat\n");
22 for (i = 0; i < vstat.rcat; i++)
23 fprintf(stdout, "%d\n", Values[i].cat);
24 break;
25
26 case O_COUNT:
27 if (options.print) {
28 if (G_verbose() > G_verbose_min())
29 fprintf(stdout, "cat%scount\n", options.fs);
30 for (i = 0; i < vstat.rcat; i++)
31 fprintf(stdout, "%d%s%d\n", Values[i].cat, options.fs, Values[i].count1);
32 }
33 if (options.total) {
34 int sum = 0;
35
36 for (i = 0; i < vstat.rcat; i++) {
37 sum += Values[i].count1;
38 }
39 fprintf(stdout, "total count%s%d\n", options.fs, sum);
40 }
41 break;
42
43 case O_AREA:
44 if (options.print) {
45 if (G_verbose() > G_verbose_min())
46 fprintf(stdout, "cat%sarea\n", options.fs);
47 for (i = 0; i < vstat.rcat; i++)
48 fprintf(stdout, "%d%s%.15g\n", Values[i].cat, options.fs, Values[i].d1);
49 }
50 if (options.total) {
51 double sum = 0.0;
52
53 for (i = 0; i < vstat.rcat; i++) {
54 sum += Values[i].d1;
55 }
56 fprintf(stdout, "total area%s%.15g\n", options.fs, sum);
57 }
58 break;
59
60 case O_COMPACT:
61 /* perimeter / perimeter of equivalent circle
62 * perimeter of equivalent circle: 2.0 * sqrt(M_PI * area) */
63 if (G_verbose() > G_verbose_min())
64 fprintf(stdout, "cat%scompact\n", options.fs);
65 for (i = 0; i < vstat.rcat; i++) {
66 Values[i].d1 = Values[i].d2 / (2.0 * sqrt(M_PI * Values[i].d1));
67 fprintf(stdout, "%d%s%.15g\n", Values[i].cat, options.fs, Values[i].d1);
68 }
69 break;
70
71 case O_FD:
72 /* 2.0 * log(perimeter) / log(area)
73 * this is neither
74 * log(perimeter) / log(perimeter of equivalent circle)
75 * perimeter of equivalent circle: 2 * sqrt(M_PI * area)
76 * nor
77 * log(area of equivalent circle) / log(area)
78 * area of equivalent circle: (perimeter / (2 * sqrt(M_PI))^2
79 *
80 * avoid division by zero:
81 * 2.0 * log(1 + perimeter) / log(1 + area) */
82 if (G_verbose() > G_verbose_min())
83 fprintf(stdout, "cat%sfd\n", options.fs);
84 for (i = 0; i < vstat.rcat; i++) {
85 if (Values[i].d1 == 1) /* log(1) == 0 */
86 Values[i].d1 += 0.000001;
87 Values[i].d1 = 2.0 * log(Values[i].d2) / log(Values[i].d1);
88 fprintf(stdout, "%d%s%.15g\n", Values[i].cat, options.fs, Values[i].d1);
89 }
90 break;
91
92 case O_PERIMETER:
93 if (G_verbose() > G_verbose_min())
94 fprintf(stdout, "cat%sperimeter\n", options.fs);
95 for (i = 0; i < vstat.rcat; i++)
96 fprintf(stdout, "%d%s%.15g\n", Values[i].cat, options.fs, Values[i].d1);
97 break;
98
99 case O_BBOX:
100 if (G_verbose() > G_verbose_min())
101 fprintf(stdout, "cat%sN%sS%sE%sW\n", options.fs, options.fs, options.fs,options.fs);
102 for (i = 0; i < vstat.rcat; i++) {
103 fprintf(stdout, "%d%s%.15g%s%.15g%s%.15g%s%.15g\n", Values[i].cat, options.fs,
104 Values[i].d1, options.fs, Values[i].d2, options.fs, Values[i].d3,
105 options.fs, Values[i].d4);
106 }
107 break;
108
109 case O_LENGTH:
110 if (options.print) {
111 if (G_verbose() > G_verbose_min())
112 fprintf(stdout, "cat%slength\n", options.fs);
113 for (i = 0; i < vstat.rcat; i++)
114 fprintf(stdout, "%d%s%.15g\n", Values[i].cat, options.fs, Values[i].d1);
115 }
116 if (options.total) {
117 double sum = 0.0;
118
119 for (i = 0; i < vstat.rcat; i++) {
120 sum += Values[i].d1;
121 }
122 fprintf(stdout, "total length%s%.15g\n", options.fs, sum);
123 }
124 break;
125 case O_SLOPE:
126 if (G_verbose() > G_verbose_min())
127 fprintf(stdout, "cat%sslope\n", options.fs);
128 for (i = 0; i < vstat.rcat; i++)
129 fprintf(stdout, "%d%s%.15g\n", Values[i].cat, options.fs, Values[i].d1);
130
131
132 break;
133 case O_SINUOUS:
134 if (G_verbose() > G_verbose_min())
135 fprintf(stdout, "cat%ssinuous\n", options.fs);
136 for (i = 0; i < vstat.rcat; i++)
137 fprintf(stdout, "%d%s%.15g\n", Values[i].cat, options.fs, Values[i].d1);
138 break;
139 case O_COOR:
140 case O_START:
141 case O_END:
142 if (G_verbose() > G_verbose_min())
143 fprintf(stdout, "cat%sx%sy%sz\n", options.fs, options.fs, options.fs);
144 for (i = 0; i < vstat.rcat; i++) {
145 if (Values[i].count1 == 1)
146 fprintf(stdout, "%d%s%.15g%s%.15g%s%.15g\n", Values[i].cat, options.fs,
147 Values[i].d1, options.fs, Values[i].d2, options.fs, Values[i].d3);
148 }
149 break;
150
151 case O_SIDES:
152 if (G_verbose() > G_verbose_min())
153 fprintf(stdout, "cat%sleft%sright\n", options.fs, options.fs);
154 for (i = 0; i < vstat.rcat; i++) {
155 if (Values[i].count1 == 1) {
156 if (Values[i].i1 >= 0)
157 sprintf(left, "%d", Values[i].i1);
158 else
159 sprintf(left, "-1"); /* NULL, no area/cat */
160 }
161 else if (Values[i].count1 > 1) {
162 sprintf(left, "-");
163 }
164 else { /* Values[i].count1 == 0 */
165 /* It can be OK if the category is assigned to an element
166 type which is not GV_BOUNDARY */
167 /* -> TODO: print only if there is boundary with that cat */
168 sprintf(left, "-");
169 }
170
171 if (Values[i].count2 == 1) {
172 if (Values[i].i2 >= 0)
173 sprintf(right, "%d", Values[i].i2);
174 else
175 sprintf(right, "-1"); /* NULL, no area/cat */
176 }
177 else if (Values[i].count2 > 1) {
178 sprintf(right, "-");
179 }
180 else { /* Values[i].count1 == 0 */
181 sprintf(right, "-");
182 }
183
184 fprintf(stdout, "%d%s%s%s%s\n", Values[i].cat, options.fs, left, options.fs, right);
185 }
186 break;
187
188 case O_QUERY:
189 if (G_verbose() > G_verbose_min())
190 fprintf(stdout, "cat%squery\n", options.fs);
191 for (i = 0; i < vstat.rcat; i++) {
192 if (Values[i].null) {
193 fprintf(stdout, "%d|-\n", Values[i].cat);
194 }
195 else {
196 switch (vstat.qtype) {
197 case (DB_C_TYPE_INT):
198 fprintf(stdout, "%d%s%d\n", Values[i].cat, options.fs, Values[i].i1);
199 break;
200 case (DB_C_TYPE_DOUBLE):
201 fprintf(stdout, "%d%s%15g\n", Values[i].cat, options.fs, Values[i].d1);
202 break;
203 case (DB_C_TYPE_STRING):
204 fprintf(stdout, "%d%s%s\n", Values[i].cat, options.fs, Values[i].str1);
205 break;
206 }
207 }
208 }
209 break;
210 case O_AZIMUTH:
211 if (G_verbose() > G_verbose_min())
212 fprintf(stdout, "cat%sazimuth\n", options.fs);
213 for (i = 0; i < vstat.rcat; i++)
214 fprintf(stdout, "%d%s%.15g\n", Values[i].cat, options.fs, Values[i].d1);
215 break;
216 }
217
218 return 0;
219 }
220
print_stat(void)221 int print_stat(void)
222 {
223 if (vstat.rcat > 0) {
224 int rcat_report;
225 if (find_cat(-1, 0) != -1)
226 rcat_report = vstat.rcat - 1;
227 else
228 rcat_report = vstat.rcat;
229
230 G_message(_("%d categories read from vector map (layer %d)"),
231 rcat_report, options.field); /* don't report cat -1 */
232 }
233 if (vstat.select > 0)
234 G_message(_("%d records selected from table (layer %d)"),
235 vstat.select, options.qfield);
236 if (vstat.exist > 0)
237 G_message(_("%d categories read from vector map exist in selection from table"),
238 vstat.exist);
239 if (vstat.notexist > 0)
240 G_message(_("%d categories read from vector map don't exist in selection from table"),
241 vstat.notexist);
242 G_message(_("%d records updated/inserted (layer %d)"),
243 vstat.update, options.field);
244 if (vstat.error > 0)
245 G_message(_("%d update/insert errors (layer %d)"),
246 vstat.error, options.field);
247 if (vstat.dupl > 0)
248 G_message(_("%d categories with more points (coordinates not loaded)"),
249 vstat.dupl);
250
251 return 0;
252 }
253