/* @(#)xtract_lines.c 1.0 9/29/89 * created by: R.L.Glenn, SCS * * Program will read vector line records, outputting lines * which match the user list of names/categories. * The resulting map attribute is arbitarily set to first category * of the user list or a user selected category number (cat_new). */ #include #include #include #include #include static int *cats_array; static int ncats_array; int cmp ( const void *pa, const void *pb) { int *p1 = (int *) pa; int *p2 = (int *) pb; if( *p1 < *p2 ) return -1; if( *p1 > *p2 ) return 1; return 0; } /* check if cat is in list */ int in_list ( int cat ) { if ( bsearch ( &cat, cats_array, ncats_array, sizeof(int), cmp ) ) return 1; return 0; } /* output reclass cats */ void extract_cats ( struct line_cats *Cats, int type_only, int field, int new ) { int i, tmp; static struct line_cats *TCats = NULL; if ( !TCats ) TCats = Vect_new_cats_struct (); /* Copy */ Vect_reset_cats ( TCats ); for ( i = 0; i < Cats->n_cats; i++ ) { Vect_cat_set ( TCats, Cats->field[i], Cats->cat[i] ); } if ( type_only && field == -1 ) /* keep all */ { return; } else if ( type_only && field > 0 ) /* keep only one field */ { Vect_reset_cats ( Cats ); if ( new > -1 ) { if ( Vect_cat_get( TCats,field,&tmp) ) Vect_cat_set ( Cats, field, new ); } else { for ( i = 0; i < TCats->n_cats; i++ ) { if ( TCats->field[i] == field ) Vect_cat_set ( Cats, field, TCats->cat[i] ); } } } else /* keep only one field, cats in list */ { Vect_reset_cats ( Cats ); if ( new > -1 ) { int found = 0; for ( i = 0; i < TCats->n_cats; i++ ) { if ( TCats->field[i] == field ) { if ( in_list(TCats->cat[i]) ) { found = 1; break; } } } if ( found ) Vect_cat_set ( Cats, field, new ); } else { for ( i = 0; i < TCats->n_cats; i++ ) { if ( TCats->field[i] == field ) { if ( in_list(TCats->cat[i]) ) { Vect_cat_set ( Cats, field, TCats->cat[i] ); } } } } } } /* check if output cats of left and right area match */ int areas_new_cats_match ( struct Map_info *In, int area1, int area2, int type_only, int field, int new ) { int i, j, found; int centroid1, centroid2; static struct line_cats *Cats1 = NULL; static struct line_cats *Cats2 = NULL; G_debug ( 4, "areas_new_cats_match area1 = %d area2 = %d", area1, area2 ); if ( !Cats1 ) Cats1 = Vect_new_cats_struct (); if ( !Cats2 ) Cats2 = Vect_new_cats_struct (); if ( area1 < 1 || area2 < 1 ) return 0; /* at least one area is missing */ centroid1 = Vect_get_area_centroid ( In, area1 ); centroid2 = Vect_get_area_centroid ( In, area2 ); if ( centroid1 < 1 || centroid2 < 1 ) return 0; /* at least one centroid is missing */ Vect_read_line ( In, NULL, Cats1, centroid1); Vect_read_line ( In, NULL, Cats2, centroid2); extract_cats ( Cats1, type_only, field, new ); extract_cats ( Cats2, type_only, field, new ); if ( Cats1->n_cats != Cats2->n_cats ) return 0; for ( i = 0; i < Cats1->n_cats; i++ ) { found = 0; for ( j = 0; j < Cats2->n_cats; j++ ) { G_debug ( 5, "%d:%d x %d:%d", Cats1->field[i], Cats1->cat[i], Cats2->field[j], Cats2->cat[j] ); if ( Cats1->field[i] == Cats2->field[j] && Cats1->cat[i] == Cats2->cat[j] ) { found = 1; break; } } if ( !found ) return 0; } G_debug ( 3, "match" ); return 1; } int xtract_line (int num_index, int *num_array, struct Map_info *In, struct Map_info *Out, int new, int select_type, int dissolve, int field, int type_only) { int line; struct line_pnts *Points; struct line_cats *Line_Cats_Old, *CCats; /* Initialize the Point structure, ONCE */ Points = Vect_new_line_struct(); Line_Cats_Old = Vect_new_cats_struct (); CCats = Vect_new_cats_struct (); cats_array = num_array; ncats_array = num_index; /* sort list */ qsort ( cats_array, ncats_array, sizeof(int), cmp ); /* Cycle through all lines */ for ( line = 1; line <= Vect_get_num_lines ( In ); line++) { int left_area=0, right_area=0; /* left/right area */ int left_field_match=0, right_field_match=0; /* left/right area field match conditions */ int left_cat_match=0, right_cat_match=0; /* left/right area cat match conditions */ int type_match=0; /* line type match */ int field_match=0; /* category of field match */ int cat_match=0; /* category found in list */ int centroid_in_area=0; /* centroid is in area */ int type; int i, tmp, write; G_debug ( 3, "Line = %d", line ); /* Get data */ type = Vect_read_line ( In, Points, Line_Cats_Old, line); G_debug ( 3, "type = %d ncats = %d", type, Line_Cats_Old->n_cats); if ( type & select_type ) type_match = 1; field_match = Vect_cat_get(Line_Cats_Old,field,&tmp); for ( i = 0; i < Line_Cats_Old->n_cats; i++ ) { G_debug ( 3, "field = %d cat = %d", Line_Cats_Old->field[i], Line_Cats_Old->cat[i]); if ( Line_Cats_Old->field[i] == field ) { if ( in_list(Line_Cats_Old->cat[i]) ) { cat_match = 1; break; } } } if ( type == GV_BOUNDARY ) { int centroid; Vect_get_line_areas ( In, line, &left_area, &right_area ); if ( left_area < 0 ) left_area = Vect_get_isle_area ( In, abs(left_area) ); if ( left_area > 0 ) { centroid = Vect_get_area_centroid ( In, left_area ); if ( centroid > 0 ) { Vect_read_line ( In, NULL, CCats, centroid); left_field_match = Vect_cat_get(CCats,field,&tmp); for ( i = 0; i < CCats->n_cats; i++ ) { if ( CCats->field[i] == field ) { if ( in_list(CCats->cat[i]) ) { left_cat_match = 1; break; } } } } } if ( right_area < 0 ) right_area = Vect_get_isle_area ( In, abs(right_area) ); if ( right_area > 0 ) { centroid = Vect_get_area_centroid ( In, right_area ); if ( centroid > 0 ) { Vect_read_line ( In, NULL, CCats, centroid); right_field_match = Vect_cat_get(CCats,field,&tmp); for ( i = 0; i < CCats->n_cats; i++ ) { if ( CCats->field[i] == field ) { if ( in_list(CCats->cat[i]) ) { right_cat_match = 1; break; } } } } } } if ( type == GV_CENTROID ) { int area; area = Vect_get_centroid_area ( In, line ); if ( area > 0 ) centroid_in_area = 1; } G_debug ( 2, "type_match = %d field_match = %d cat_match = %d", type_match, field_match, cat_match ); G_debug ( 2, "left_area = %d left_field_match = %d left_cat_match = %d", left_area, left_field_match, left_cat_match ); G_debug ( 2, "right_area = %d right_field_match = %d right_cat_match = %d", right_area, right_field_match, right_cat_match ); /* Check if the line match conditions */ write = 0; if ( type_only && field == -1 ) /* type only */ { /* line */ if ( type_match ) write = 1; /* centroid */ if ( type == GV_CENTROID && (select_type & GV_AREA) && centroid_in_area ) write = 1; /* areas */ if ( type == GV_BOUNDARY && ( left_area || right_area ) ) { if ( !dissolve || !areas_new_cats_match ( In, left_area, right_area, type_only, field, new ) ) write = 1; } } else if ( type_only && field > 0 ) /* type and field only */ { /* line */ if ( type_match && field_match ) write = 1; /* centroid */ if ( type == GV_CENTROID && (select_type & GV_AREA) && centroid_in_area && field_match ) write = 1; /* areas */ if ( type == GV_BOUNDARY && (select_type & GV_AREA) && ( left_field_match || right_field_match ) ) { if ( !dissolve || !areas_new_cats_match ( In, left_area, right_area, type_only, field, new ) ) write = 1; } } else /* type, field and category */ { /* line */ if ( type_match && cat_match ) write = 1; /* centroid */ if ( type == GV_CENTROID && (select_type & GV_AREA) && centroid_in_area && cat_match ) write = 1; /* areas */ if ( type == GV_BOUNDARY && (select_type & GV_AREA) && ( left_cat_match || right_cat_match ) ) { if ( !dissolve || !areas_new_cats_match ( In, left_area, right_area, type_only, field, new ) ) write = 1; } } G_debug ( 2, "write = %d", write ); if ( write ) { extract_cats ( Line_Cats_Old, type_only, field, new ); Vect_write_line (Out, type, Points, Line_Cats_Old); } } /* end lines section */ return(0) ; }