123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- /*!
- \file remove_duplicates.c
-
- \brief Vector library - clean geometry (remove duplicates)
-
- Higher level functions for reading/writing/manipulating vectors.
- (C) 2001-2008 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.
-
- \author Radim Blazek
-
- \date 2001
- */
- #include <stdlib.h>
- #include <grass/gis.h>
- #include <grass/Vect.h>
- #include <grass/glocale.h>
- /*!
- \brief Remove duplicate lines from vector map.
-
- Remove duplicate lines of given types from vector map. Duplicate lines may be optionaly
- written to error map. Input map must be opened on level 2 for update. Categories are merged.
-
- \param Map vector map where duplicate lines will be deleted
- \param type type of line to be delete
- \param Err vector map where duplicate lines will be written or NULL
- \param msgout file pointer where messages will be written or NULL
- \return void
- */
- void
- Vect_remove_duplicates ( struct Map_info *Map, int type, struct Map_info *Err, FILE *msgout )
- {
- struct line_pnts *APoints, *BPoints;
- struct line_cats *ACats, *BCats, *Cats;
- int i, j, c, atype, btype, bline;
- int nlines, nbcats_orig;
- BOUND_BOX ABox;
- struct ilist *List;
- int ndupl;
-
- APoints = Vect_new_line_struct ();
- BPoints = Vect_new_line_struct ();
- ACats = Vect_new_cats_struct ();
- BCats = Vect_new_cats_struct ();
- Cats = Vect_new_cats_struct ();
- List = Vect_new_list ();
-
- nlines = Vect_get_num_lines (Map);
- G_debug (1, "nlines = %d", nlines );
- /* Go through all lines in vector, for each select lines which overlap MBR of
- * this line and check if some of them is identical. If someone is identical
- * remove current line. (In each step just one line is deleted)
- */
- ndupl = 0;
- if ( msgout )
- fprintf (msgout, "%s: %5d", _("Duplicates"), ndupl );
- for ( i = 1; i <= nlines; i++ ){
- if ( !Vect_line_alive ( Map, i ) ) continue;
- atype = Vect_read_line (Map, APoints, ACats, i);
- if ( !(atype & type) ) continue;
- Vect_line_box ( APoints, &ABox );
- Vect_select_lines_by_box ( Map, &ABox, type, List);
- G_debug (3, " %d lines selected by box", List->n_values);
-
- for ( j = 0; j < List->n_values; j++ ){
- bline = List->value[j];
- G_debug (3, " j = %d bline = %d", j, bline);
- if ( i == bline ) continue;
-
- btype = Vect_read_line (Map, BPoints, BCats, bline);
- /* check for duplicates */
- if (!Vect_line_check_duplicate (APoints, BPoints, Vect_is_3d(Map)))
- continue;
- /* Lines area identical -> remove current */
- if ( Err ) {
- Vect_write_line ( Err, atype, APoints, ACats );
- }
- Vect_delete_line (Map, i);
- /* Merge categories */
- nbcats_orig = BCats->n_cats;
-
- for ( c = 0; c < ACats->n_cats; c++ )
- Vect_cat_set ( BCats, ACats->field[c], ACats->cat[c] );
-
- if ( BCats->n_cats > nbcats_orig ) {
- G_debug ( 4, "cats merged: n_cats %d -> %d", nbcats_orig, BCats->n_cats );
- Vect_rewrite_line ( Map, bline, btype, BPoints, BCats );
- }
-
- ndupl++;
-
- if ( msgout ) {
- fprintf (msgout, "\r%s: %5d", _("Duplicates"), ndupl );
- fflush (msgout);
- }
-
- break; /* line was deleted -> take the next one */
- }
- nlines = Vect_get_num_lines (Map); /* For future when lines with cats will be rewritten */
- G_debug (3, "nlines = %d\n", nlines );
- }
- if ( msgout )
- fprintf (msgout, "\n");
- return;
- }
- /*!
- \brief Check for duplicate lines
- \param APoints first line geometry
- \param BPoints second line geometry
- \return 1 duplicate
- \return 0 not duplicate
- */
- int Vect_line_check_duplicate(const struct line_pnts *APoints,
- const struct line_pnts *BPoints, int with_z)
- {
- int k;
- int npoints;
- int forw, backw;
- if ( APoints->n_points != BPoints->n_points )
- return 0;
-
- npoints = APoints->n_points;
- /* Forward */
- forw = 1;
- for (k = 0; k < APoints->n_points; k++) {
- if (APoints->x[k] != BPoints->x[k] ||
- APoints->y[k] != BPoints->y[k] ||
- (with_z && APoints->z[k] != BPoints->z[k])) {
- forw = 0;
- break;
- }
- }
- /* Backward */
- backw = 1;
- for (k = 0; k < APoints->n_points; k++) {
- if (APoints->x[k] != BPoints->x[npoints - k - 1] ||
- APoints->y[k] != BPoints->y[npoints - k - 1] ||
- (with_z && APoints->z[k] != BPoints->z[npoints - k - 1])) {
- backw = 0;
- break;
- }
- }
-
- if (!forw && !backw)
- return 0;
-
- return 1;
- }
|