GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
remove_duplicates.c
Go to the documentation of this file.
1 
20 #include <stdlib.h>
21 #include <grass/gis.h>
22 #include <grass/Vect.h>
23 #include <grass/glocale.h>
24 
37 void
38 Vect_remove_duplicates(struct Map_info *Map, int type, struct Map_info *Err)
39 {
40  struct line_pnts *APoints, *BPoints;
41  struct line_cats *ACats, *BCats, *Cats;
42  int i, j, c, atype, btype, bline;
43  int nlines, nbcats_orig;
44  BOUND_BOX ABox;
45  struct ilist *List;
46  int ndupl;
47 
48 
49  APoints = Vect_new_line_struct();
50  BPoints = Vect_new_line_struct();
51  ACats = Vect_new_cats_struct();
52  BCats = Vect_new_cats_struct();
53  Cats = Vect_new_cats_struct();
54  List = Vect_new_list();
55 
56  nlines = Vect_get_num_lines(Map);
57 
58  G_debug(1, "nlines = %d", nlines);
59  /* Go through all lines in vector, for each select lines which overlap MBR of
60  * this line and check if some of them is identical. If someone is identical
61  * remove current line. (In each step just one line is deleted)
62  */
63 
64  ndupl = 0;
65 
66  for (i = 1; i <= nlines; i++) {
67  G_percent(i, nlines, 1);
68  if (!Vect_line_alive(Map, i))
69  continue;
70 
71  atype = Vect_read_line(Map, APoints, ACats, i);
72  if (!(atype & type))
73  continue;
74 
75  Vect_line_box(APoints, &ABox);
76  Vect_select_lines_by_box(Map, &ABox, type, List);
77  G_debug(3, " %d lines selected by box", List->n_values);
78 
79  for (j = 0; j < List->n_values; j++) {
80  bline = List->value[j];
81  G_debug(3, " j = %d bline = %d", j, bline);
82  if (i == bline)
83  continue;
84 
85  btype = Vect_read_line(Map, BPoints, BCats, bline);
86 
87  /* check for duplicates */
88  if (!Vect_line_check_duplicate(APoints, BPoints, Vect_is_3d(Map)))
89  continue;
90 
91  /* Lines area identical -> remove current */
92  if (Err) {
93  Vect_write_line(Err, atype, APoints, ACats);
94  }
95 
96  Vect_delete_line(Map, i);
97 
98  /* Merge categories */
99  nbcats_orig = BCats->n_cats;
100 
101  for (c = 0; c < ACats->n_cats; c++)
102  Vect_cat_set(BCats, ACats->field[c], ACats->cat[c]);
103 
104  if (BCats->n_cats > nbcats_orig) {
105  G_debug(4, "cats merged: n_cats %d -> %d", nbcats_orig,
106  BCats->n_cats);
107  Vect_rewrite_line(Map, bline, btype, BPoints, BCats);
108  }
109 
110  ndupl++;
111 
112  break; /* line was deleted -> take the next one */
113  }
114  nlines = Vect_get_num_lines(Map); /* For future when lines with cats will be rewritten */
115  G_debug(3, "nlines = %d\n", nlines);
116  }
117  G_verbose_message("Removed duplicates: %d", ndupl);
118 }
119 
129 int Vect_line_check_duplicate(const struct line_pnts *APoints,
130  const struct line_pnts *BPoints, int with_z)
131 {
132  int k;
133  int npoints;
134  int forw, backw;
135 
136  if (APoints->n_points != BPoints->n_points)
137  return 0;
138 
139  npoints = APoints->n_points;
140 
141  /* Forward */
142  forw = 1;
143  for (k = 0; k < APoints->n_points; k++) {
144  if (APoints->x[k] != BPoints->x[k] ||
145  APoints->y[k] != BPoints->y[k] ||
146  (with_z && APoints->z[k] != BPoints->z[k])) {
147  forw = 0;
148  break;
149  }
150  }
151 
152  /* Backward */
153  backw = 1;
154  for (k = 0; k < APoints->n_points; k++) {
155  if (APoints->x[k] != BPoints->x[npoints - k - 1] ||
156  APoints->y[k] != BPoints->y[npoints - k - 1] ||
157  (with_z && APoints->z[k] != BPoints->z[npoints - k - 1])) {
158  backw = 0;
159  break;
160  }
161  }
162 
163  if (!forw && !backw)
164  return 0;
165 
166  return 1;
167 }
int Vect_line_box(struct line_pnts *Points, BOUND_BOX *Box)
Get bounding box of line.
Definition: line.c:771
struct line_pnts * Vect_new_line_struct()
Creates and initializes a struct line_pnts.
Definition: line.c:57
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
int Vect_cat_set(struct line_cats *Cats, int field, int cat)
Add new field/cat to category structure if doesn&#39;t exist yet.
int G_percent(long n, long d, int s)
Print percent complete messages.
Definition: percent.c:63
int Vect_is_3d(struct Map_info *Map)
Check if vector map is 3D (with z)
void G_verbose_message(const char *msg,...)
Print a message to stderr but only if module is in verbose mode.
Definition: lib/gis/error.c:95
int Vect_rewrite_line(struct Map_info *Map, int line, int type, struct line_pnts *points, struct line_cats *cats)
Rewrites feature info at the given offset.
void Vect_remove_duplicates(struct Map_info *Map, int type, struct Map_info *Err)
Remove duplicate lines from vector map.
int Vect_line_alive(struct Map_info *Map, int line)
Check if feature is alive or dead.
int Vect_select_lines_by_box(struct Map_info *Map, BOUND_BOX *Box, int type, struct ilist *list)
Select lines by box.
struct line_cats * Vect_new_cats_struct()
Creates and initializes line_cats structure.
int Vect_get_num_lines(struct Map_info *map)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition: level_two.c:69
int Vect_line_check_duplicate(const struct line_pnts *APoints, const struct line_pnts *BPoints, int with_z)
Check for duplicate lines.
tuple Map
Definition: render.py:1310
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
int Vect_delete_line(struct Map_info *Map, int line)
Delete feature.
long Vect_write_line(struct Map_info *Map, int type, struct line_pnts *points, struct line_cats *cats)
Writes new feature to the end of file (table)
int Vect_read_line(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line)
Read vector feature.