GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
bridges.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 
25 static void
26 remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err);
27 
43 void
44 Vect_remove_bridges(struct Map_info *Map, struct Map_info *Err)
45 {
46  remove_bridges(Map, 0, Err);
47 }
48 
64 void
65 Vect_chtype_bridges(struct Map_info *Map, struct Map_info *Err)
66 {
67  remove_bridges(Map, 1, Err);
68 }
69 
70 /*
71  Called by Vect_remove_bridges() and Vect_chtype_bridges():
72  chtype = 0 -> works like Vect_remove_bridges()
73  chtype = 1 -> works like Vect_chtype_bridges()
74 
75  Algorithm: Go thorough all lines,
76  if both sides of the line have left and side 0 (candidate) do this check:
77  follow adjacent lines in one direction (nearest to the right at the end node),
78  if we reach this line again without dangle in the way, but with this line
79  traversed from other side it is a bridge.
80 
81  List of all lines in chain is created during the cycle.
82  */
83 void
84 remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err)
85 {
86  int i, type, nlines, line;
87  int left, right, node1, node2, current_line, next_line;
88  int bridges_removed = 0; /* number of removed bridges */
89  int lines_removed = 0; /* number of lines removed */
90  char *lmsg;
91  struct Plus_head *Plus;
92  struct line_pnts *Points;
93  struct line_cats *Cats;
94  struct ilist *CycleList;
95  struct ilist *BridgeList;
96 
97  int dangle, other_side;
98 
99  if (chtype)
100  lmsg = "changed lines";
101  else
102  lmsg = "removed lines";
103 
104  Plus = &(Map->plus);
105 
106  Points = Vect_new_line_struct();
107  Cats = Vect_new_cats_struct();
108  CycleList = Vect_new_list();
109  BridgeList = Vect_new_list();
110 
111  nlines = Vect_get_num_lines(Map);
112 
113  G_debug(1, "nlines = %d", nlines);
114 
115  for (line = 1; line <= nlines; line++) {
116  G_percent(line, nlines, 1);
117  if (!Vect_line_alive(Map, line))
118  continue;
119 
120  type = Vect_read_line(Map, NULL, NULL, line);
121  if (!(type & GV_BOUNDARY))
122  continue;
123 
124  Vect_get_line_areas(Map, line, &left, &right);
125 
126  if (left != 0 || right != 0)
127  continue; /* Cannot be bridge */
128 
129  G_debug(2, "line %d - bridge candidate", line);
130 
131  Vect_get_line_nodes(Map, line, &node1, &node2);
132 
133  if (abs(node1) == abs(node2))
134  continue; /* either zero length or loop -> cannot be a bridge */
135 
136  current_line = -line; /* we start with negative (go forward, node2 ) */
137 
138  dangle = 0;
139  other_side = 0;
140  Vect_reset_list(CycleList);
141  Vect_reset_list(BridgeList);
142  while (1) {
143  next_line =
144  dig_angle_next_line(Plus, current_line, GV_RIGHT,
145  GV_BOUNDARY);
146 
147  /* Add this line to the list */
148  if (Vect_val_in_list(CycleList, abs(next_line))) /* other side -> bridge chain */
149  Vect_list_append(BridgeList, abs(next_line));
150  else
151  Vect_list_append(CycleList, abs(next_line));
152 
153  if (abs(next_line) == abs(current_line)) {
154  G_debug(4, " dangle -> no bridge");
155  dangle = 1;
156  break;
157  }
158  if (abs(next_line) == line) { /* start line reached */
159  /* which side */
160  if (next_line < 0) { /* other side (connected by node 2) */
161  G_debug(5, " other side reached");
162  other_side = 1;
163  }
164  else { /* start side */
165  break;
166  }
167  }
168 
169  current_line = -next_line; /* change the sign to look at the next node in following cycle */
170  }
171 
172  if (!dangle && other_side) {
173  G_debug(3, " line %d is part of bridge chain", line);
174 
175  for (i = 0; i < BridgeList->n_values; i++) {
176  Vect_read_line(Map, Points, Cats, BridgeList->value[i]);
177 
178  if (Err) {
179  Vect_write_line(Err, GV_BOUNDARY, Points, Cats);
180  }
181 
182  if (!chtype)
183  Vect_delete_line(Map, BridgeList->value[i]);
184  else
185  Vect_rewrite_line(Map, BridgeList->value[i], GV_LINE,
186  Points, Cats);
187 
188  lines_removed++;
189  }
190  bridges_removed++;
191  }
192  }
193  G_verbose_message("Removed lines: %d", lines_removed);
194  G_verbose_message("Removed bridges: %d", bridges_removed);
195 }
int Vect_get_line_nodes(struct Map_info *Map, int line, int *n1, int *n2)
Get line nodes.
Definition: level_two.c:247
int Vect_get_line_areas(struct Map_info *Map, int line, int *left, int *right)
Get area/isle ids on the left and right.
Definition: level_two.c:272
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 dig_angle_next_line(struct Plus_head *plus, plus_t current_line, int side, int type)
Find number line of next angle to follow an line.
Definition: plus_area.c:474
int G_percent(long n, long d, int s)
Print percent complete messages.
Definition: percent.c:63
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.
int Vect_reset_list(struct ilist *list)
Reset ilist structure.
int Vect_list_append(struct ilist *list, int val)
Append new item to the end of list if not yet present.
int Vect_line_alive(struct Map_info *Map, int line)
Check if feature is alive or dead.
struct line_cats * Vect_new_cats_struct()
Creates and initializes line_cats structure.
return NULL
Definition: dbfopen.c:1394
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
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_val_in_list(struct ilist *list, int val)
Find a given item in the list.
void Vect_remove_bridges(struct Map_info *Map, struct Map_info *Err)
Remove bridges from vector map.
Definition: bridges.c:44
void Vect_chtype_bridges(struct Map_info *Map, struct Map_info *Err)
Change type of bridges in vector map.
Definition: bridges.c:65
int Vect_read_line(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line)
Read vector feature.