/* *************************************************************** * * * * MODULE: v.category * * * * AUTHOR(S): Radim Blazek * * * * PURPOSE: Category manipulations * * * * COPYRIGHT: (C) 2001 by the GRASS Development Team * * * * This program is free software under the * * GNU General Public License (>=v2). * * Read the file COPYING that comes with GRASS * * for details. * * * **************************************************************/ #include #include #include #include #define O_ADD 1 #define O_DEL 2 #define O_REP 3 #define O_PRN 4 #define O_SUM 5 #define O_CHFIELD 6 #define O_TYPE_REP 7 /* report number of features for each type */ #define FRTYPES 7 /* number of field report types */ #define FR_POINT 0 #define FR_LINE 1 #define FR_BOUNDARY 2 #define FR_CENTROID 3 #define FR_AREA 4 #define FR_UNKNOWN 5 #define FR_ALL 6 typedef struct { int field; char *table; int count[FRTYPES]; int min[FRTYPES], max[FRTYPES]; } FREPORT; int main (int argc, char *argv[]) { struct Map_info In, Out; static struct line_pnts *Points; struct line_cats *Cats; struct field_info *Fi; int i, j, ret, option, otype, type, with_z, step; int n_areas, centr, new_centr; double x, y; int cat, ocat, *fields, nfields, field; struct GModule *module; struct Option *in_opt, *out_opt, *option_opt, *type_opt; struct Option *cat_opt, *field_opt, *step_opt; struct Flag *shell; FREPORT **freps; int nfreps, rtype, fld; module = G_define_module(); module->keywords = _("vector"); module->description = "Attach, delete or report vector categories to map geometry."; in_opt = G_define_standard_option(G_OPT_V_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->required = NO; type_opt = G_define_standard_option(G_OPT_V_TYPE) ; option_opt = G_define_option(); option_opt->key = "option"; option_opt->type = TYPE_STRING; option_opt->required = NO; option_opt->multiple = NO; option_opt->options = "add,del,chlayer,sum,report,print"; option_opt->answer = "add"; option_opt->description = "Action to be done:\n" "\tadd - add a new category\n" "\tdel - delete category\n" "\tchlayer - change layer number (e.g. layer=3,1 changes layer 3 to layer 1)\n" "\tsum - add the value specified by cat option to the current category value\n" "\treport - print report (statistics), in shell style:\n" "\t\tlayer type count min max\n" "\tprint - print category values, more cats in the same layer are separated by '/'"; cat_opt = G_define_standard_option(G_OPT_V_CAT); cat_opt->answer = "1"; field_opt = G_define_standard_option(G_OPT_V_FIELD); field_opt->answer = "1"; field_opt->multiple = YES; step_opt = G_define_option(); step_opt->key = "step"; step_opt->type = TYPE_INTEGER; step_opt->required = NO; step_opt->multiple = NO; step_opt->answer = "1"; step_opt->description = "Category increment"; shell = G_define_flag(); shell->key = 'g'; shell->description = "shell script style, currently only for report"; G_gisinit(argv[0]); if (G_parser (argc, argv)) exit(-1); /* read options */ option = 0; switch ( option_opt->answer[0] ) { case ( 'a' ): option = O_ADD; break; case ( 'd' ): option = O_DEL; break; case ( 'c' ): option = O_CHFIELD; G_warning("Database connection and attribute tables for concerned layers are not changed"); break; case ( 's' ): option = O_SUM; break; case ( 'r' ): option = O_REP; break; case ( 'p' ): option = O_PRN; break; } cat = atoi( cat_opt->answer ); step = atoi( step_opt->answer ); i = 0; otype = 0; while (type_opt->answers[i]) { switch ( type_opt->answers[i][0] ) { case 'p': otype |= GV_POINT; break; case 'l': otype |= GV_LINE; break; case 'b': otype |= GV_BOUNDARY; break; case 'c': otype |= GV_CENTROID; break; case 'a': otype |= GV_AREA; break; } i++; } /* read fields */ i = 0; nfields = 0; while (field_opt->answers[i]) { nfields++; i++; } fields = (int *) G_malloc ( nfields * sizeof(int) ); i = 0; while (field_opt->answers[i]) { fields[i] = atoi( field_opt->answers[i] ); i++; } if ( nfields > 1 && option != O_PRN && option != O_CHFIELD ) G_fatal_error ( _("Too many layers for this operation") ); if ( nfields != 2 && option == O_CHFIELD ) G_fatal_error ( _("2 layers must be specified") ); if ( (option != O_REP) && (option != O_PRN) ) { if (out_opt->answer == NULL) { G_fatal_error ( _("Output vector wasn't entered.") ); } Vect_check_input_output_name ( in_opt->answer, out_opt->answer, GV_FATAL_EXIT ); } Points = Vect_new_line_struct (); Cats = Vect_new_cats_struct (); /* open input vector */ Vect_set_open_level (2); Vect_open_old (&In, in_opt->answer, ""); /* open output vector if needed */ if (option == O_ADD || option == O_DEL || option == O_CHFIELD || option == O_SUM) { with_z = In.head.with_z; Vect_set_fatal_error (GV_FATAL_PRINT); if (0 > Vect_open_new (&Out, out_opt->answer, with_z)) { Vect_close (&In); exit (1); } Vect_copy_head_data (&In, &Out); Vect_hist_copy (&In, &Out); Vect_hist_command ( &Out ); } switch ( option) { case (O_ADD): /* Lines */ while ( (type = Vect_read_next_line (&In, Points, Cats)) > 0) { if ( type & otype ) { if( (Vect_cat_get (Cats, fields[0], &ocat)) == 0) { Vect_cat_set (Cats, fields[0], cat); cat += step; } } Vect_write_line ( &Out, type, Points, Cats ); } /* Areas */ if ( otype & GV_AREA ) { n_areas = Vect_get_num_areas ( &In ); new_centr = 0; for ( i = 1; i <= n_areas; i++ ) { centr = Vect_get_area_centroid ( &In, i ); if ( centr > 0 ) continue; /* Centroid exists and may be processed as line */ ret = Vect_get_point_in_area ( &In, i, &x, &y ); if ( ret < 0 ) { G_warning ("Cannot calculate area centroid" ); continue; } Vect_reset_line ( Points ); Vect_reset_cats ( Cats ); Vect_append_point ( Points, x, y, 0.0 ); Vect_cat_set (Cats, fields[0], cat); cat += step; Vect_write_line ( &Out, GV_CENTROID, Points, Cats ); new_centr++; } fprintf (stdout, "%d new centroids placed in output map\n", new_centr ); } break; case (O_DEL): while ( (type = Vect_read_next_line (&In, Points, Cats)) > 0) { if ( type & otype ) { ret = Vect_cat_del (Cats, fields[0]); } Vect_write_line ( &Out, type, Points, Cats ); } break; case (O_CHFIELD): while ( (type = Vect_read_next_line (&In, Points, Cats)) > 0) { if ( type & otype ) { for ( i = 0 ; i < Cats->n_cats; i++ ) { if ( Cats->field[i] == fields[0] ) { Cats->field[i] = fields[1]; } } } Vect_write_line ( &Out, type, Points, Cats ); } break; case (O_SUM): while ( (type = Vect_read_next_line (&In, Points, Cats)) > 0) { if ( type & otype ) { for ( i = 0 ; i < Cats->n_cats; i++ ) { if ( Cats->field[i] == fields[0] ) { Cats->cat[i] += cat; } } } Vect_write_line ( &Out, type, Points, Cats ); } break; case (O_REP): nfreps = 0; freps = NULL; while ( (type = Vect_read_next_line (&In, Points, Cats)) > 0) { switch (type) { case (GV_POINT): rtype = FR_POINT; break; case (GV_LINE): rtype = FR_LINE; break; case (GV_BOUNDARY): rtype = FR_BOUNDARY; break; case (GV_CENTROID): rtype = FR_CENTROID; break; default: rtype = FR_UNKNOWN; } for (i=0; i < Cats->n_cats; i++) { field = Cats->field[i]; cat = Cats->cat[i]; ret = FALSE; for (j=0; j < nfreps; j++) { if ( freps[j]->field == field ) { fld = j; ret = TRUE; break; } } if ( !ret ) /* field report doesn't exist */ { nfreps++; freps = (FREPORT **) G_realloc ( freps, nfreps * sizeof (FREPORT *)); fld = nfreps - 1; freps[fld] = (FREPORT *) G_calloc ( 1, sizeof (FREPORT)); freps[fld]->field = field; if ((Fi = Vect_get_field (&In, field)) != NULL) { freps[fld]->table = G_store (Fi->table); } else { freps[fld]->table = '\0'; } } freps[fld]->count[rtype]++; freps[fld]->count[FR_ALL]++; if ( (freps[fld]->min[rtype] == 0) || freps[fld]->min[rtype] > cat) freps[fld]->min[rtype] = cat; if ( (freps[fld]->max[rtype] == 0) || freps[fld]->max[rtype] < cat) freps[fld]->max[rtype] = cat; if ( (freps[fld]->min[FR_ALL] == 0) || freps[fld]->min[FR_ALL] > cat) freps[fld]->min[FR_ALL] = cat; if ( (freps[fld]->max[FR_ALL] == 0) || freps[fld]->max[FR_ALL] < cat) freps[fld]->max[FR_ALL] = cat; } } for (i=0; i < nfreps; i++) { if ( shell->answer ) { if ( freps[i]->count[FR_POINT] > 0 ) fprintf (stdout, "%d point %d %d %d\n", freps[i]->field, freps[i]->count[FR_POINT], freps[i]->min[FR_POINT], freps[i]->max[FR_POINT]); if ( freps[i]->count[FR_LINE] > 0 ) fprintf (stdout, "%d line %d %d %d\n", freps[i]->field, freps[i]->count[FR_LINE], freps[i]->min[FR_LINE], freps[i]->max[FR_LINE]); if ( freps[i]->count[FR_BOUNDARY] > 0 ) fprintf (stdout, "%d boundary %d %d %d\n", freps[i]->field, freps[i]->count[FR_BOUNDARY], freps[i]->min[FR_BOUNDARY], freps[i]->max[FR_BOUNDARY]); if ( freps[i]->count[FR_CENTROID] > 0 ) fprintf (stdout, "%d centroid %d %d %d\n", freps[i]->field, freps[i]->count[FR_CENTROID], freps[i]->min[FR_CENTROID], freps[i]->max[FR_CENTROID]); if ( freps[i]->count[FR_AREA] > 0 ) fprintf (stdout, "%d area %d %d %d\n", freps[i]->field, freps[i]->count[FR_AREA], freps[i]->min[FR_AREA], freps[i]->max[FR_AREA]); } else { if (freps[i]->table != '\0') { fprintf (stdout, "LAYER/TABLE %d/%s:\n", freps[i]->field, freps[i]->table); } else { fprintf (stdout, "LAYER %d:\n", freps[i]->field); } fprintf (stdout, "type count min max\n"); fprintf (stdout, "point %7d %10d %10d\n", freps[i]->count[FR_POINT], freps[i]->min[FR_POINT], freps[i]->max[FR_POINT]); fprintf (stdout, "line %7d %10d %10d\n", freps[i]->count[FR_LINE], freps[i]->min[FR_LINE], freps[i]->max[FR_LINE]); fprintf (stdout, "boundary %7d %10d %10d\n", freps[i]->count[FR_BOUNDARY], freps[i]->min[FR_BOUNDARY], freps[i]->max[FR_BOUNDARY]); fprintf (stdout, "centroid %7d %10d %10d\n", freps[i]->count[FR_CENTROID], freps[i]->min[FR_CENTROID], freps[i]->max[FR_CENTROID]); fprintf (stdout, "area %7d %10d %10d\n", freps[i]->count[FR_AREA], freps[i]->min[FR_AREA], freps[i]->max[FR_AREA]); fprintf (stdout, "all %7d %10d %10d\n", freps[i]->count[FR_ALL], freps[i]->min[FR_ALL], freps[i]->max[FR_ALL]); } } break; case (O_PRN): while ( (type = Vect_read_next_line (&In, Points, Cats)) > 0) { int has = 0; if ( !(type & otype) ) continue; /* Check if the line has at least one cat */ for (i=0; i < nfields; i++) { for (j=0; j < Cats->n_cats; j++) { if ( Cats->field[j] == fields[i] ) { has = 1; break; } } } if ( !has ) continue; for (i=0; i < nfields; i++) { int first = 1; if ( i > 0 ) fprintf (stdout, "|" ); for (j=0; j < Cats->n_cats; j++) { if ( Cats->field[j] == fields[i] ) { if ( !first ) fprintf (stdout, "/"); fprintf (stdout, "%d", Cats->cat[j] ); first = 0; } } } fprintf (stdout, "\n" ); } break; } if (option == O_ADD || option == O_DEL || option == O_CHFIELD || option == O_SUM) { Vect_copy_tables ( &In, &Out, 0 ); Vect_build (&Out, stdout); Vect_close (&Out); } Vect_close (&In); exit(0) ; }