|
@@ -17,10 +17,20 @@
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
#include <grass/vector.h>
|
|
|
+#include <grass/rbtree.h>
|
|
|
#include <grass/glocale.h>
|
|
|
|
|
|
+static int cmp_int(const void *a, const void *b)
|
|
|
+{
|
|
|
+ const int *ai = a;
|
|
|
+ const int *bi = b;
|
|
|
+
|
|
|
+ return (*ai < *bi ? -1 : (*ai > *bi));
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
-remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err);
|
|
|
+remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err,
|
|
|
+ int *lrm, int *brm);
|
|
|
|
|
|
/*!
|
|
|
\brief Remove bridges from vector map.
|
|
@@ -33,13 +43,16 @@ remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err);
|
|
|
|
|
|
\param Map input map where bridges are deleted
|
|
|
\param Err vector map where deleted bridges are written or NULL
|
|
|
+ \param lines_removed number of lines removed
|
|
|
+ \param bridges_removed Err number of bridges removed
|
|
|
|
|
|
\return
|
|
|
*/
|
|
|
void
|
|
|
-Vect_remove_bridges(struct Map_info *Map, struct Map_info *Err)
|
|
|
+Vect_remove_bridges(struct Map_info *Map, struct Map_info *Err,
|
|
|
+ int *lines_removed, int *bridges_removed)
|
|
|
{
|
|
|
- remove_bridges(Map, 0, Err);
|
|
|
+ remove_bridges(Map, 0, Err, lines_removed, bridges_removed);
|
|
|
}
|
|
|
|
|
|
/*!
|
|
@@ -54,14 +67,17 @@ Vect_remove_bridges(struct Map_info *Map, struct Map_info *Err)
|
|
|
|
|
|
\param Map input map where bridges are changed
|
|
|
\param Err vector map where changed bridges are written or NULL
|
|
|
+ \param lines_changed number of lines changed
|
|
|
+ \param bridges_changed Err number of bridges changed
|
|
|
|
|
|
\return
|
|
|
*/
|
|
|
|
|
|
void
|
|
|
-Vect_chtype_bridges(struct Map_info *Map, struct Map_info *Err)
|
|
|
+Vect_chtype_bridges(struct Map_info *Map, struct Map_info *Err,
|
|
|
+ int *lines_changed, int *bridges_changed)
|
|
|
{
|
|
|
- remove_bridges(Map, 1, Err);
|
|
|
+ remove_bridges(Map, 1, Err, lines_changed, bridges_changed);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -78,17 +94,18 @@ Vect_chtype_bridges(struct Map_info *Map, struct Map_info *Err)
|
|
|
List of all lines in chain is created during the cycle.
|
|
|
*/
|
|
|
void
|
|
|
-remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err)
|
|
|
+remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err,
|
|
|
+ int *lrm, int *brm)
|
|
|
{
|
|
|
- int i, type, nlines, line;
|
|
|
- int left, right, node1, node2, current_line, next_line;
|
|
|
+ int i, type, nlines, line, *bline;
|
|
|
+ int left, right, node1, node2, current_line, next_line, abs_line;
|
|
|
int bridges_removed = 0; /* number of removed bridges */
|
|
|
int lines_removed = 0; /* number of lines removed */
|
|
|
struct Plus_head *Plus;
|
|
|
struct line_pnts *Points;
|
|
|
struct line_cats *Cats;
|
|
|
- struct ilist *CycleList;
|
|
|
- struct ilist *BridgeList;
|
|
|
+ struct RB_TREE *CycleTree, *BridgeTree;
|
|
|
+ struct RB_TRAV trav;
|
|
|
|
|
|
int dangle, other_side;
|
|
|
|
|
@@ -96,8 +113,9 @@ remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err)
|
|
|
|
|
|
Points = Vect_new_line_struct();
|
|
|
Cats = Vect_new_cats_struct();
|
|
|
- CycleList = Vect_new_list();
|
|
|
- BridgeList = Vect_new_list();
|
|
|
+
|
|
|
+ CycleTree = rbtree_create(cmp_int, sizeof(int));
|
|
|
+ BridgeTree = rbtree_create(cmp_int, sizeof(int));
|
|
|
|
|
|
nlines = Vect_get_num_lines(Map);
|
|
|
|
|
@@ -126,22 +144,27 @@ remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err)
|
|
|
|
|
|
current_line = -line; /* we start with negative (go forward, node2 ) */
|
|
|
|
|
|
+ G_debug(3, "current line: %d", line);
|
|
|
dangle = 0;
|
|
|
other_side = 0;
|
|
|
- Vect_reset_list(CycleList);
|
|
|
- Vect_reset_list(BridgeList);
|
|
|
+ rbtree_clear(CycleTree);
|
|
|
+ rbtree_clear(BridgeTree);
|
|
|
+
|
|
|
while (1) {
|
|
|
next_line =
|
|
|
dig_angle_next_line(Plus, current_line, GV_RIGHT,
|
|
|
GV_BOUNDARY, NULL);
|
|
|
+ abs_line = abs(next_line);
|
|
|
|
|
|
/* Add this line to the list */
|
|
|
- /* TODO: Vect_val_in_list() and Vect_list_append() behave O(n)
|
|
|
- * change to O(log n) */
|
|
|
- if (Vect_val_in_list(CycleList, abs(next_line))) /* other side -> bridge chain */
|
|
|
- Vect_list_append(BridgeList, abs(next_line));
|
|
|
- else
|
|
|
- G_ilist_add(CycleList, abs(next_line)); /* not in list, can add new line fast */
|
|
|
+ if (rbtree_find(CycleTree, (void *)&abs_line)) {
|
|
|
+ if (!rbtree_find(BridgeTree, (void *)&abs_line)) {
|
|
|
+ rbtree_insert(BridgeTree, (void *)&abs_line);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ rbtree_insert(CycleTree, (void *)&abs_line);
|
|
|
+ }
|
|
|
|
|
|
if (abs(next_line) == abs(current_line)) {
|
|
|
G_debug(4, " dangle -> no bridge");
|
|
@@ -165,17 +188,19 @@ remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err)
|
|
|
if (!dangle && other_side) {
|
|
|
G_debug(3, " line %d is part of bridge chain", line);
|
|
|
|
|
|
- for (i = 0; i < BridgeList->n_values; i++) {
|
|
|
- Vect_read_line(Map, Points, Cats, BridgeList->value[i]);
|
|
|
+ rbtree_init_trav(&trav, BridgeTree);
|
|
|
+ /* for (i = 0; i < BridgeList->n_values; i++) { */
|
|
|
+ while ((bline = rbtree_traverse(&trav))) {
|
|
|
+ Vect_read_line(Map, Points, Cats, *bline);
|
|
|
|
|
|
if (Err) {
|
|
|
Vect_write_line(Err, GV_BOUNDARY, Points, Cats);
|
|
|
}
|
|
|
|
|
|
if (!chtype)
|
|
|
- Vect_delete_line(Map, BridgeList->value[i]);
|
|
|
+ Vect_delete_line(Map, *bline);
|
|
|
else
|
|
|
- Vect_rewrite_line(Map, BridgeList->value[i], GV_LINE,
|
|
|
+ Vect_rewrite_line(Map, *bline, GV_LINE,
|
|
|
Points, Cats);
|
|
|
|
|
|
lines_removed++;
|
|
@@ -183,6 +208,17 @@ remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err)
|
|
|
bridges_removed++;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ Vect_destroy_line_struct(Points);
|
|
|
+ Vect_destroy_cats_struct(Cats);
|
|
|
+ rbtree_destroy(CycleTree);
|
|
|
+ rbtree_destroy(BridgeTree);
|
|
|
+
|
|
|
+ if (lrm)
|
|
|
+ *lrm = lines_removed;
|
|
|
+ if (brm)
|
|
|
+ *brm = bridges_removed;
|
|
|
+
|
|
|
G_verbose_message("Removed lines: %d", lines_removed);
|
|
|
G_verbose_message("Removed bridges: %d", bridges_removed);
|
|
|
}
|