main.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. /* ***************************************************************
  2. * *
  3. * * MODULE: v.category
  4. * *
  5. * * AUTHOR(S): Radim Blazek
  6. * * OGR support by Martin Landa <landa.martin gmail.com> (2009)
  7. * *
  8. * * PURPOSE: Category manipulations
  9. * *
  10. * * COPYRIGHT: (C) 2001-2009 by the GRASS Development Team
  11. * *
  12. * * This program is free software under the
  13. * * GNU General Public License (>=v2).
  14. * * Read the file COPYING that comes with GRASS
  15. * * for details.
  16. * *
  17. * **************************************************************/
  18. #include <stdlib.h>
  19. #include <grass/glocale.h>
  20. #include <grass/gis.h>
  21. #include <grass/vector.h>
  22. #define O_ADD 1
  23. #define O_DEL 2
  24. #define O_REP 3
  25. #define O_PRN 4
  26. #define O_SUM 5
  27. #define O_CHFIELD 6
  28. #define O_TYPE_REP 7 /* report number of features for each type */
  29. #define O_TRANS 8
  30. #define O_LYR 9
  31. #define FRTYPES 9 /* number of field report types */
  32. #define FR_POINT 0
  33. #define FR_LINE 1
  34. #define FR_BOUNDARY 2
  35. #define FR_CENTROID 3
  36. #define FR_AREA 4
  37. #define FR_FACE 5
  38. #define FR_KERNEL 6
  39. #define FR_UNKNOWN 7
  40. #define FR_ALL 8
  41. typedef struct
  42. {
  43. int field;
  44. char *table;
  45. int count[FRTYPES];
  46. int min[FRTYPES], max[FRTYPES];
  47. } FREPORT;
  48. int main(int argc, char *argv[])
  49. {
  50. struct Map_info In, Out;
  51. static struct line_pnts *Points;
  52. struct line_cats *Cats, *TCats;
  53. struct field_info *Fi;
  54. struct cat_list *Clist;
  55. int i, j, ret, option, otype, type, with_z, step, id;
  56. int n_areas, centr, new_centr, nmodified;
  57. int open_level;
  58. double x, y;
  59. int cat, ocat, scat, *fields, nfields, field;
  60. struct GModule *module;
  61. struct Option *in_opt, *out_opt, *option_opt, *type_opt;
  62. struct Option *cat_opt, *field_opt, *step_opt, *id_opt;
  63. struct Flag *shell, *notab;
  64. FREPORT **freps;
  65. int nfreps, rtype, fld;
  66. char *desc;
  67. module = G_define_module();
  68. G_add_keyword(_("vector"));
  69. G_add_keyword(_("category"));
  70. G_add_keyword(_("layer"));
  71. module->description =
  72. _("Attaches, deletes or reports vector categories to map geometry.");
  73. in_opt = G_define_standard_option(G_OPT_V_INPUT);
  74. field_opt = G_define_standard_option(G_OPT_V_FIELD);
  75. field_opt->multiple = YES;
  76. field_opt->guisection = _("Selection");
  77. type_opt = G_define_standard_option(G_OPT_V3_TYPE);
  78. type_opt->answer = "point,line,centroid,face";
  79. type_opt->guisection = _("Selection");
  80. id_opt = G_define_standard_option(G_OPT_V_IDS);
  81. id_opt->label = _("Feature ids (by default all features are processed)");
  82. id_opt->guisection = _("Selection");
  83. out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  84. out_opt->required = NO;
  85. option_opt = G_define_option();
  86. option_opt->key = "option";
  87. option_opt->type = TYPE_STRING;
  88. option_opt->required = YES;
  89. option_opt->multiple = NO;
  90. option_opt->options = "add,del,chlayer,sum,report,print,layers,transfer";
  91. option_opt->description = _("Action to be done");
  92. desc = NULL;
  93. G_asprintf(&desc,
  94. "add;%s;"
  95. "del;%s;"
  96. "chlayer;%s;"
  97. "sum;%s;"
  98. "transfer;%s;"
  99. "report;%s;"
  100. "print;%s;"
  101. "layers;%s",
  102. _("add a category to features without category in the given layer"),
  103. _("delete category (cat=-1 to delete all categories of given layer)"),
  104. _("change layer number (e.g. layer=3,1 changes layer 3 to layer 1)"),
  105. _("add the value specified by cat option to the current category value"),
  106. _("copy values from one layer to another (e.g. layer=1,2,3 copies values from layer 1 to layer 2 and 3)"),
  107. _("print report (statistics), in shell style: layer type count min max"),
  108. _("print category values, more cats in the same layer are separated by '/'"),
  109. _("print only layer numbers"));
  110. option_opt->descriptions = desc;
  111. cat_opt = G_define_standard_option(G_OPT_V_CAT);
  112. cat_opt->answer = "1";
  113. step_opt = G_define_option();
  114. step_opt->key = "step";
  115. step_opt->type = TYPE_INTEGER;
  116. step_opt->required = NO;
  117. step_opt->multiple = NO;
  118. step_opt->answer = "1";
  119. step_opt->description = _("Category increment");
  120. shell = G_define_flag();
  121. shell->key = 'g';
  122. shell->label = _("Shell script style, currently only for report");
  123. shell->description = _("Format: layer type count min max");
  124. notab = G_define_standard_flag(G_FLG_V_TABLE);
  125. notab->description = _("Do not copy attribute table(s)");
  126. G_gisinit(argv[0]);
  127. if (G_parser(argc, argv))
  128. exit(EXIT_FAILURE);
  129. /* read options */
  130. option = 0;
  131. switch (option_opt->answer[0]) {
  132. case ('a'):
  133. option = O_ADD;
  134. break;
  135. case ('d'):
  136. option = O_DEL;
  137. break;
  138. case ('c'):
  139. option = O_CHFIELD;
  140. G_warning(_("Database connection and attribute tables for concerned layers are not changed"));
  141. break;
  142. case ('s'):
  143. option = O_SUM;
  144. break;
  145. case ('t'):
  146. option = O_TRANS;
  147. break;
  148. case ('r'):
  149. option = O_REP;
  150. break;
  151. case ('p'):
  152. option = O_PRN;
  153. break;
  154. case ('l'):
  155. option = O_LYR;
  156. break;
  157. }
  158. if (option == O_LYR) {
  159. /* print vector layer numbers */
  160. /* open vector on level 2 head only, this is why this option
  161. * is processed here, all other options need (?) to fully open
  162. * the input vector */
  163. Vect_set_open_level(2);
  164. if (Vect_open_old_head2(&In, in_opt->answer, "", field_opt->answer) < 2) {
  165. G_fatal_error(_("Unable to open vector map <%s> at topological level %d"),
  166. Vect_get_full_name(&In), 2);
  167. }
  168. if (In.format == GV_FORMAT_NATIVE) {
  169. nfields = Vect_cidx_get_num_fields(&In);
  170. for (i = 0; i < nfields; i++) {
  171. if ((field = Vect_cidx_get_field_number(&In, i)) > 0)
  172. fprintf(stdout, "%d\n", field);
  173. }
  174. }
  175. else
  176. fprintf(stdout, "%s\n", field_opt->answer);
  177. Vect_close(&In);
  178. exit(EXIT_SUCCESS);
  179. }
  180. cat = atoi(cat_opt->answer);
  181. step = atoi(step_opt->answer);
  182. otype = Vect_option_to_types(type_opt);
  183. if (cat < 0 && option == O_ADD)
  184. G_fatal_error(_("Invalid category number (must be equal to or greater than 0). "
  185. "Normally category number starts at 1."));
  186. /* collect ids */
  187. if (id_opt->answer) {
  188. Clist = Vect_new_cat_list();
  189. Clist->field = atoi(field_opt->answer);
  190. ret = Vect_str_to_cat_list(id_opt->answer, Clist);
  191. if (ret > 0) {
  192. G_warning(_n("%d error in id option",
  193. "%d errors in id option",
  194. ret), ret);
  195. }
  196. }
  197. else {
  198. Clist = NULL;
  199. }
  200. if ((option != O_REP) && (option != O_PRN) && (option != O_LYR)) {
  201. if (out_opt->answer == NULL)
  202. G_fatal_error(_("Output vector wasn't entered"));
  203. Vect_check_input_output_name(in_opt->answer, out_opt->answer,
  204. G_FATAL_EXIT);
  205. }
  206. Points = Vect_new_line_struct();
  207. Cats = Vect_new_cats_struct();
  208. /* do we need topology ? */
  209. if ((option == O_ADD && (otype & GV_AREA)) ||
  210. (option == O_REP && (otype & GV_AREA)) ||
  211. (option == O_TRANS) || /* topo for cidx check */
  212. (option == O_LYR)) /* topo for cidx check */
  213. open_level = 2;
  214. else
  215. open_level = 1;
  216. /* open input vector */
  217. if (open_level > 1) {
  218. Vect_set_open_level(open_level);
  219. if (Vect_open_old2(&In, in_opt->answer, "", field_opt->answer) < open_level) {
  220. G_warning(_("Unable to open vector map <%s> at topological level %d"),
  221. Vect_get_full_name(&In), open_level);
  222. open_level = 1;
  223. }
  224. }
  225. if (open_level == 1) {
  226. Vect_set_open_level(open_level);
  227. if (Vect_open_old2(&In, in_opt->answer, "", field_opt->answer) < open_level) {
  228. G_fatal_error(_("Unable to open vector map <%s> at topological level %d"),
  229. Vect_get_full_name(&In), open_level);
  230. }
  231. }
  232. /* read fields */
  233. i = nfields = 0;
  234. while (field_opt->answers[i++])
  235. nfields++;
  236. fields = (int *)G_malloc(nfields * sizeof(int));
  237. i = 0;
  238. while (field_opt->answers[i]) {
  239. fields[i] = Vect_get_field_number(&In, field_opt->answers[i]);
  240. i++;
  241. }
  242. if (nfields > 1 && option != O_PRN && option != O_CHFIELD && option != O_TRANS)
  243. G_fatal_error(_("Too many layers for this operation"));
  244. if (nfields != 2 && option == O_CHFIELD)
  245. G_fatal_error(_("2 layers must be specified"));
  246. if (option == O_TRANS && open_level == 1 && nfields < 2) {
  247. G_fatal_error(_("2 layers must be specified"));
  248. }
  249. if (option == O_TRANS && open_level > 1) {
  250. /* check if field[>0] already exists */
  251. if (nfields > 1) {
  252. for(i = 1; i < nfields; i++) {
  253. if (Vect_cidx_get_field_index(&In, fields[i]) != -1)
  254. G_warning(_("Categories already exist in layer %d"), fields[i]);
  255. }
  256. }
  257. /* find next free layer number */
  258. else if (nfields == 1) {
  259. int max = -1;
  260. for (i = 0; i < Vect_cidx_get_num_fields(&In); i++) {
  261. if (max < Vect_cidx_get_field_number(&In, i))
  262. max = Vect_cidx_get_field_number(&In, i);
  263. }
  264. max++;
  265. nfields++;
  266. fields = (int *)G_realloc(fields, nfields * sizeof(int));
  267. fields[nfields - 1] = max;
  268. }
  269. }
  270. if (otype & GV_AREA && option == O_TRANS && !(otype & GV_CENTROID))
  271. otype |= GV_CENTROID;
  272. /* open output vector if needed */
  273. if (option == O_ADD || option == O_DEL || option == O_CHFIELD ||
  274. option == O_SUM || option == O_TRANS) {
  275. with_z = Vect_is_3d(&In);
  276. if (0 > Vect_open_new(&Out, out_opt->answer, with_z)) {
  277. Vect_close(&In);
  278. exit(EXIT_FAILURE);
  279. }
  280. Vect_copy_head_data(&In, &Out);
  281. Vect_hist_copy(&In, &Out);
  282. Vect_hist_command(&Out);
  283. }
  284. id = 0;
  285. nmodified = 0;
  286. if (option == O_ADD || option == O_DEL || option == O_CHFIELD ||
  287. option == O_SUM || option == O_TRANS) {
  288. G_message(_("Processing features..."));
  289. }
  290. switch (option) {
  291. case (O_ADD):
  292. /* Lines */
  293. while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) {
  294. id++;
  295. if (type & otype && (!Clist ||
  296. (Clist &&
  297. Vect_cat_in_cat_list(id, Clist) == TRUE))) {
  298. if ((Vect_cat_get(Cats, fields[0], &ocat)) == 0) {
  299. if (ocat < 0) {
  300. if (Vect_cat_set(Cats, fields[0], cat) > 0) {
  301. nmodified++;
  302. }
  303. cat += step;
  304. }
  305. }
  306. }
  307. Vect_write_line(&Out, type, Points, Cats);
  308. }
  309. /* Areas */
  310. if ((otype & GV_AREA) && open_level > 1) {
  311. n_areas = Vect_get_num_areas(&In);
  312. new_centr = 0;
  313. for (i = 1; i <= n_areas; i++) {
  314. centr = Vect_get_area_centroid(&In, i);
  315. if (centr > 0)
  316. continue; /* Centroid exists and may be processed as line */
  317. ret = Vect_get_point_in_area(&In, i, &x, &y);
  318. if (ret < 0) {
  319. G_warning(_("Unable to calculate area centroid"));
  320. continue;
  321. }
  322. Vect_reset_line(Points);
  323. Vect_reset_cats(Cats);
  324. Vect_append_point(Points, x, y, 0.0);
  325. if (Vect_cat_set(Cats, fields[0], cat) > 0) {
  326. nmodified++;
  327. }
  328. cat += step;
  329. Vect_write_line(&Out, GV_CENTROID, Points, Cats);
  330. new_centr++;
  331. }
  332. if (new_centr > 0)
  333. G_message(_n("%d new centroid placed in output map",
  334. "%d new centroids placed in output map",
  335. new_centr), new_centr);
  336. }
  337. break;
  338. case (O_TRANS):
  339. TCats = Vect_new_cats_struct();
  340. /* Lines */
  341. while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) {
  342. Vect_reset_cats(TCats);
  343. id++;
  344. if (type & otype && (!Clist ||
  345. (Clist &&
  346. Vect_cat_in_cat_list(id, Clist) == TRUE))) {
  347. int n = Cats->n_cats;
  348. scat = -1;
  349. for (i = 0; i < n; i++) {
  350. if (Cats->field[i] == fields[0]) {
  351. scat = Cats->cat[i];
  352. Vect_cat_set(TCats, 1, scat);
  353. }
  354. }
  355. if (scat > -1) {
  356. n = TCats->n_cats;
  357. for (i = 0; i < n; i++) {
  358. scat = TCats->cat[i];
  359. for (i = 1; i < nfields; i++) {
  360. if (Vect_cat_set(Cats, fields[i], scat) > 0) {
  361. G_debug(4, "Copy cat %i of field %i to into field %i", scat, fields[0], fields[i]);
  362. }
  363. }
  364. }
  365. nmodified++;
  366. }
  367. }
  368. Vect_write_line(&Out, type, Points, Cats);
  369. }
  370. Vect_destroy_cats_struct(TCats);
  371. break;
  372. case (O_DEL):
  373. while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) {
  374. id++;
  375. if (type & otype && (!Clist ||
  376. (Clist &&
  377. Vect_cat_in_cat_list(id, Clist) == TRUE))) {
  378. ret = Vect_field_cat_del(Cats, fields[0], cat);
  379. if (ret > 0) {
  380. nmodified++;
  381. }
  382. }
  383. Vect_write_line(&Out, type, Points, Cats);
  384. }
  385. break;
  386. case (O_CHFIELD):
  387. while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) {
  388. id++;
  389. if (type & otype && (!Clist ||
  390. (Clist &&
  391. Vect_cat_in_cat_list(id, Clist) == TRUE))) {
  392. i = 0;
  393. while (i < Cats->n_cats) {
  394. if (Cats->field[i] == fields[0]) {
  395. int found = -1;
  396. /* check if cat already exists in layer fields[1] */
  397. for (j = 0; j < Cats->n_cats; j++) {
  398. if (Cats->field[j] == fields[1] &&
  399. Cats->cat[j] == Cats->cat[i]) {
  400. found = j;
  401. break;
  402. }
  403. }
  404. /* does not exist, change layer */
  405. if (found < 0) {
  406. Cats->field[i] = fields[1];
  407. i++;
  408. }
  409. /* exists already in fields[1], delete from fields[0] */
  410. else
  411. Vect_field_cat_del(Cats, fields[0], Cats->cat[found]);
  412. nmodified++;
  413. }
  414. }
  415. }
  416. Vect_write_line(&Out, type, Points, Cats);
  417. }
  418. break;
  419. case (O_SUM):
  420. while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) {
  421. id++;
  422. if (type & otype && (!Clist ||
  423. (Clist &&
  424. Vect_cat_in_cat_list(id, Clist) == TRUE))) {
  425. for (i = 0; i < Cats->n_cats; i++) {
  426. if (Cats->field[i] == fields[0]) {
  427. Cats->cat[i] += cat;
  428. }
  429. }
  430. nmodified++;
  431. }
  432. Vect_write_line(&Out, type, Points, Cats);
  433. }
  434. break;
  435. case (O_REP):
  436. nfreps = 0;
  437. freps = NULL;
  438. while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) {
  439. id++;
  440. if (Clist && Vect_cat_in_cat_list(id, Clist) == FALSE)
  441. continue;
  442. switch (type) {
  443. case (GV_POINT):
  444. rtype = FR_POINT;
  445. break;
  446. case (GV_LINE):
  447. rtype = FR_LINE;
  448. break;
  449. case (GV_BOUNDARY):
  450. rtype = FR_BOUNDARY;
  451. break;
  452. case (GV_CENTROID):
  453. rtype = FR_CENTROID;
  454. break;
  455. case (GV_FACE):
  456. rtype = FR_FACE;
  457. break;
  458. case (GV_KERNEL):
  459. rtype = FR_KERNEL;
  460. break;
  461. default:
  462. rtype = FR_UNKNOWN;
  463. }
  464. for (i = 0; i < Cats->n_cats; i++) {
  465. field = Cats->field[i];
  466. cat = Cats->cat[i];
  467. ret = FALSE;
  468. for (j = 0; j < nfreps; j++) {
  469. if (freps[j]->field == field) {
  470. fld = j;
  471. ret = TRUE;
  472. break;
  473. }
  474. }
  475. if (!ret) { /* field report doesn't exist */
  476. nfreps++;
  477. freps =
  478. (FREPORT **) G_realloc(freps,
  479. nfreps * sizeof(FREPORT *));
  480. fld = nfreps - 1;
  481. freps[fld] = (FREPORT *) G_calloc(1, sizeof(FREPORT));
  482. freps[fld]->field = field;
  483. for (j = 0; j < FRTYPES; j++) {
  484. /* cat '0' is valid category number */
  485. freps[fld]->min[j] = -1;
  486. }
  487. if ((Fi = Vect_get_field(&In, field)) != NULL) {
  488. freps[fld]->table = G_store(Fi->table);
  489. }
  490. else {
  491. freps[fld]->table = '\0';
  492. }
  493. }
  494. freps[fld]->count[rtype]++;
  495. freps[fld]->count[FR_ALL]++;
  496. if (freps[fld]->min[rtype] == -1 ||
  497. freps[fld]->min[rtype] > cat)
  498. freps[fld]->min[rtype] = cat;
  499. if ((freps[fld]->max[rtype] == 0) ||
  500. freps[fld]->max[rtype] < cat)
  501. freps[fld]->max[rtype] = cat;
  502. if (freps[fld]->min[FR_ALL] == -1 ||
  503. freps[fld]->min[FR_ALL] > cat)
  504. freps[fld]->min[FR_ALL] = cat;
  505. if ((freps[fld]->max[FR_ALL] == 0) ||
  506. freps[fld]->max[FR_ALL] < cat)
  507. freps[fld]->max[FR_ALL] = cat;
  508. }
  509. }
  510. /* Areas */
  511. if ((otype & GV_AREA) && open_level > 1 && !Clist) {
  512. n_areas = Vect_get_num_areas(&In);
  513. for (i = 1; i <= n_areas; i++) {
  514. int k;
  515. centr = Vect_get_area_centroid(&In, i);
  516. if (centr <= 0)
  517. continue; /* Area without centroid */
  518. Vect_read_line(&In, NULL, Cats, centr);
  519. for (j = 0; j < Cats->n_cats; j++) {
  520. field = Cats->field[j];
  521. cat = Cats->cat[j];
  522. ret = FALSE;
  523. for (k = 0; k < nfreps; k++) {
  524. if (freps[k]->field == field) {
  525. fld = k;
  526. ret = TRUE;
  527. break;
  528. }
  529. }
  530. if (!ret) { /* field report doesn't exist */
  531. nfreps++;
  532. freps =
  533. (FREPORT **) G_realloc(freps,
  534. nfreps * sizeof(FREPORT *));
  535. fld = nfreps - 1;
  536. freps[fld] = (FREPORT *) G_calloc(1, sizeof(FREPORT));
  537. freps[fld]->field = field;
  538. for (j = 0; j < FRTYPES; j++) {
  539. /* cat '0' is valid category number */
  540. freps[fld]->min[k] = -1;
  541. }
  542. if ((Fi = Vect_get_field(&In, field)) != NULL) {
  543. freps[fld]->table = G_store(Fi->table);
  544. }
  545. else {
  546. freps[fld]->table = '\0';
  547. }
  548. }
  549. freps[fld]->count[FR_AREA]++;
  550. if (freps[fld]->min[FR_AREA] == -1 ||
  551. freps[fld]->min[FR_AREA] > cat)
  552. freps[fld]->min[FR_AREA] = cat;
  553. if ((freps[fld]->max[FR_AREA] == 0) ||
  554. freps[fld]->max[FR_AREA] < cat)
  555. freps[fld]->max[FR_AREA] = cat;
  556. }
  557. }
  558. }
  559. for (i = 0; i < nfreps; i++) {
  560. if (shell->answer) {
  561. if (freps[i]->count[FR_POINT] > 0)
  562. fprintf(stdout, "%d point %d %d %d\n", freps[i]->field,
  563. freps[i]->count[FR_POINT],
  564. (freps[i]->min[FR_POINT] < 0 ? 0 : freps[i]->min[FR_POINT]),
  565. freps[i]->max[FR_POINT]);
  566. if (freps[i]->count[FR_LINE] > 0)
  567. fprintf(stdout, "%d line %d %d %d\n", freps[i]->field,
  568. freps[i]->count[FR_LINE],
  569. (freps[i]->min[FR_LINE] < 0 ? 0 : freps[i]->min[FR_LINE]),
  570. freps[i]->max[FR_LINE]);
  571. if (freps[i]->count[FR_BOUNDARY] > 0)
  572. fprintf(stdout, "%d boundary %d %d %d\n", freps[i]->field,
  573. freps[i]->count[FR_BOUNDARY],
  574. (freps[i]->min[FR_BOUNDARY] < 0 ? 0 : freps[i]->min[FR_BOUNDARY]),
  575. freps[i]->max[FR_BOUNDARY]);
  576. if (freps[i]->count[FR_CENTROID] > 0)
  577. fprintf(stdout, "%d centroid %d %d %d\n", freps[i]->field,
  578. freps[i]->count[FR_CENTROID],
  579. (freps[i]->min[FR_BOUNDARY] < 0 ? 0 : freps[i]->min[FR_BOUNDARY]),
  580. freps[i]->max[FR_CENTROID]);
  581. if (freps[i]->count[FR_AREA] > 0)
  582. fprintf(stdout, "%d area %d %d %d\n", freps[i]->field,
  583. freps[i]->count[FR_AREA],
  584. (freps[i]->min[FR_AREA] < 0 ? 0 : freps[i]->min[FR_AREA]),
  585. freps[i]->max[FR_AREA]);
  586. if (freps[i]->count[FR_FACE] > 0)
  587. fprintf(stdout, "%d face %d %d %d\n", freps[i]->field,
  588. freps[i]->count[FR_FACE],
  589. (freps[i]->min[FR_FACE] < 0 ? 0 : freps[i]->min[FR_FACE]),
  590. freps[i]->max[FR_FACE]);
  591. if (freps[i]->count[FR_KERNEL] > 0)
  592. fprintf(stdout, "%d kernel %d %d %d\n", freps[i]->field,
  593. freps[i]->count[FR_KERNEL],
  594. (freps[i]->min[FR_KERNEL] < 0 ? 0 : freps[i]->min[FR_KERNEL]),
  595. freps[i]->max[FR_KERNEL]);
  596. if (freps[i]->count[FR_ALL] > 0)
  597. fprintf(stdout, "%d all %d %d %d\n", freps[i]->field,
  598. freps[i]->count[FR_ALL],
  599. (freps[i]->min[FR_ALL] < 0 ? 0 : freps[i]->min[FR_ALL]),
  600. freps[i]->max[FR_ALL]);
  601. }
  602. else {
  603. if (freps[i]->table != '\0') {
  604. fprintf(stdout, "%s: %d/%s\n", _("Layer/table"),
  605. freps[i]->field, freps[i]->table);
  606. }
  607. else {
  608. fprintf(stdout, "%s: %d\n", _("Layer"), freps[i]->field);
  609. }
  610. fprintf(stdout, _("type count min max\n"));
  611. fprintf(stdout, "%s %7d %10d %10d\n", _("point"),
  612. freps[i]->count[FR_POINT],
  613. (freps[i]->min[FR_POINT] < 0) ? 0 : freps[i]->min[FR_POINT],
  614. freps[i]->max[FR_POINT]);
  615. fprintf(stdout, "%s %7d %10d %10d\n", _("line"),
  616. freps[i]->count[FR_LINE],
  617. (freps[i]->min[FR_LINE] < 0) ? 0 : freps[i]->min[FR_LINE],
  618. freps[i]->max[FR_LINE]);
  619. fprintf(stdout, "%s %7d %10d %10d\n", _("boundary"),
  620. freps[i]->count[FR_BOUNDARY],
  621. (freps[i]->min[FR_BOUNDARY] < 0) ? 0 : freps[i]->min[FR_BOUNDARY],
  622. freps[i]->max[FR_BOUNDARY]);
  623. fprintf(stdout, "%s %7d %10d %10d\n", _("centroid"),
  624. freps[i]->count[FR_CENTROID],
  625. (freps[i]->min[FR_CENTROID] < 0) ? 0 : freps[i]->min[FR_CENTROID],
  626. freps[i]->max[FR_CENTROID]);
  627. fprintf(stdout, "%s %7d %10d %10d\n", _("area"),
  628. freps[i]->count[FR_AREA],
  629. (freps[i]->min[FR_AREA] < 0) ? 0 : freps[i]->min[FR_AREA],
  630. freps[i]->max[FR_AREA]);
  631. fprintf(stdout, "%s %7d %10d %10d\n", _("face"),
  632. freps[i]->count[FR_FACE],
  633. (freps[i]->min[FR_FACE] < 0) ? 0 : freps[i]->min[FR_FACE],
  634. freps[i]->max[FR_FACE]);
  635. fprintf(stdout, "%s %7d %10d %10d\n", _("kernel"),
  636. freps[i]->count[FR_KERNEL],
  637. (freps[i]->min[FR_KERNEL] < 0) ? 0 : freps[i]->min[FR_KERNEL],
  638. freps[i]->max[FR_KERNEL]);
  639. fprintf(stdout, "%s %7d %10d %10d\n", _("all"),
  640. freps[i]->count[FR_ALL],
  641. (freps[i]->min[FR_ALL] < 0) ? 0 : freps[i]->min[FR_ALL],
  642. freps[i]->max[FR_ALL]);
  643. }
  644. }
  645. break;
  646. case (O_PRN):
  647. while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) {
  648. id++;
  649. int has = 0;
  650. if (!(type & otype))
  651. continue;
  652. if (Clist && Vect_cat_in_cat_list(id, Clist) == FALSE)
  653. continue;
  654. /* Check if the line has at least one cat */
  655. for (i = 0; i < nfields; i++) {
  656. for (j = 0; j < Cats->n_cats; j++) {
  657. if (Cats->field[j] == fields[i]) {
  658. has = 1;
  659. break;
  660. }
  661. }
  662. }
  663. if (!has)
  664. continue;
  665. for (i = 0; i < nfields; i++) {
  666. int first = 1;
  667. if (i > 0)
  668. fprintf(stdout, "|");
  669. for (j = 0; j < Cats->n_cats; j++) {
  670. if (Cats->field[j] == fields[i]) {
  671. if (!first)
  672. fprintf(stdout, "/");
  673. fprintf(stdout, "%d", Cats->cat[j]);
  674. first = 0;
  675. }
  676. }
  677. }
  678. fprintf(stdout, "\n");
  679. }
  680. break;
  681. }
  682. if (option == O_ADD || option == O_DEL || option == O_CHFIELD ||
  683. option == O_SUM || option == O_TRANS){
  684. if (!notab->answer){
  685. G_message(_("Copying attribute table(s)..."));
  686. if (Vect_copy_tables(&In, &Out, 0))
  687. G_warning(_("Failed to copy attribute table to output map"));
  688. }
  689. Vect_build(&Out);
  690. Vect_close(&Out);
  691. }
  692. if (option == O_TRANS && nmodified > 0)
  693. for(i = 1; i < nfields; i++)
  694. G_important_message(_("Categories copied from layer %d to layer %d"),
  695. fields[0], fields[i]);
  696. G_done_msg(_n("%d feature modified.",
  697. "%d features modified.",
  698. nmodified), nmodified);
  699. Vect_close(&In);
  700. exit(EXIT_SUCCESS);
  701. }