|
@@ -20,6 +20,40 @@
|
|
|
#include <grass/vector.h>
|
|
|
#include <grass/glocale.h>
|
|
|
|
|
|
+/* compare category structures
|
|
|
+ * return 0 identical
|
|
|
+ * return 1 not identical
|
|
|
+ */
|
|
|
+static int compare_cats(struct line_cats *ACats, struct line_cats *BCats)
|
|
|
+{
|
|
|
+ int i, j;
|
|
|
+
|
|
|
+ if (ACats->n_cats == 0 && BCats->n_cats == 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (ACats->n_cats == 0 && BCats->n_cats > 0)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ if (ACats->n_cats > 0 && BCats->n_cats == 0)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ for (i = 0; i < ACats->n_cats; i++) {
|
|
|
+ int found = 0;
|
|
|
+
|
|
|
+ for (j = 0; j < BCats->n_cats; j++) {
|
|
|
+ if (ACats->cat[i] == BCats->cat[j] &&
|
|
|
+ ACats->field[i] == BCats->field[j]) {
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!found)
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*!
|
|
|
\brief Merge lines or boundaries in vector map.
|
|
|
|
|
@@ -42,21 +76,16 @@
|
|
|
int Vect_merge_lines(struct Map_info *Map, int type, int *new_lines,
|
|
|
struct Map_info *Err)
|
|
|
{
|
|
|
- int line, nlines, i, c, first, last, next_line, curr_line;
|
|
|
+ int line, nlines, i, first, last, next_line, curr_line;
|
|
|
int merged = 0, newl = 0;
|
|
|
- int next_node, direction, node_n_lines, same_type;
|
|
|
+ int next_node, direction, node_n_lines, ltype, lines_type;
|
|
|
struct Plus_head *Plus;
|
|
|
struct ilist *List;
|
|
|
struct line_pnts *MPoints, *Points;
|
|
|
struct line_cats *MCats, *Cats;
|
|
|
struct P_line *Line;
|
|
|
|
|
|
- if ((type & GV_BOUNDARY) && (type & GV_LINE)) {
|
|
|
- G_warning
|
|
|
- ("Merging is done only with either lines or boundaries, not both types at the same time");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (!(type & GV_BOUNDARY) && !(type & GV_LINE)) {
|
|
|
+ if (!(type & GV_LINES)) {
|
|
|
G_warning
|
|
|
("Merging is done with lines or boundaries only, not with other types");
|
|
|
return 0;
|
|
@@ -78,9 +107,12 @@ int Vect_merge_lines(struct Map_info *Map, int type, int *new_lines,
|
|
|
continue;
|
|
|
|
|
|
Line = Plus->Line[line];
|
|
|
+ ltype = Line->type;
|
|
|
|
|
|
- if (!(Line->type & type))
|
|
|
+ if (!(ltype & type))
|
|
|
continue;
|
|
|
+
|
|
|
+ Vect_read_line(Map, NULL, MCats, line);
|
|
|
|
|
|
/* special cases:
|
|
|
* - loop back to start boundary via several other boundaries
|
|
@@ -91,48 +123,61 @@ int Vect_merge_lines(struct Map_info *Map, int type, int *new_lines,
|
|
|
/* go backward as long as there is only one other line/boundary at the current node */
|
|
|
G_debug(3, "go backward");
|
|
|
next_node = 0;
|
|
|
- if (type == GV_LINE) {
|
|
|
+ if (ltype == GV_LINE) {
|
|
|
struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
|
|
|
+
|
|
|
next_node = topo->N1;
|
|
|
}
|
|
|
- else if (type == GV_BOUNDARY) {
|
|
|
+ else if (ltype == GV_BOUNDARY) {
|
|
|
struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
|
|
|
+
|
|
|
next_node = topo->N1;
|
|
|
}
|
|
|
first = -line;
|
|
|
while (1) {
|
|
|
node_n_lines = Vect_get_node_n_lines(Map, next_node);
|
|
|
- same_type = 0;
|
|
|
+ /* count lines/boundaries at this node */
|
|
|
+ lines_type = 0;
|
|
|
next_line = first;
|
|
|
for (i = 0; i < node_n_lines; i++) {
|
|
|
curr_line = Vect_get_node_line(Map, next_node, i);
|
|
|
- if ((Plus->Line[abs(curr_line)]->type & type)) {
|
|
|
- same_type++;
|
|
|
- if (abs(curr_line) != abs(first))
|
|
|
- next_line = curr_line;
|
|
|
+ if ((Plus->Line[abs(curr_line)]->type & GV_LINES))
|
|
|
+ lines_type++;
|
|
|
+ if ((Plus->Line[abs(curr_line)]->type == ltype)) {
|
|
|
+ if (abs(curr_line) != abs(first)) {
|
|
|
+ Vect_read_line(Map, NULL, Cats, abs(curr_line));
|
|
|
+
|
|
|
+ /* catgories must be identical */
|
|
|
+ if (compare_cats(MCats, Cats) == 0)
|
|
|
+ next_line = curr_line;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- if (same_type == 2 && abs(next_line) != abs(first) &&
|
|
|
+ if (lines_type == 2 && abs(next_line) != abs(first) &&
|
|
|
abs(next_line) != line) {
|
|
|
first = next_line;
|
|
|
|
|
|
if (first < 0) {
|
|
|
- if (type == GV_LINE) {
|
|
|
+ if (ltype == GV_LINE) {
|
|
|
struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[-first]->topo;
|
|
|
+
|
|
|
next_node = topo->N1;
|
|
|
}
|
|
|
- else if (type == GV_BOUNDARY) {
|
|
|
+ else if (ltype == GV_BOUNDARY) {
|
|
|
struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[-first]->topo;
|
|
|
+
|
|
|
next_node = topo->N1;
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
- if (type == GV_LINE) {
|
|
|
+ if (ltype == GV_LINE) {
|
|
|
struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[first]->topo;
|
|
|
+
|
|
|
next_node = topo->N2;
|
|
|
}
|
|
|
- else if (type == GV_BOUNDARY) {
|
|
|
+ else if (ltype == GV_BOUNDARY) {
|
|
|
struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[first]->topo;
|
|
|
+
|
|
|
next_node = topo->N2;
|
|
|
}
|
|
|
}
|
|
@@ -148,62 +193,75 @@ int Vect_merge_lines(struct Map_info *Map, int type, int *new_lines,
|
|
|
last = -first;
|
|
|
|
|
|
if (last < 0) {
|
|
|
- if (type == GV_LINE) {
|
|
|
+ if (ltype == GV_LINE) {
|
|
|
struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[-last]->topo;
|
|
|
+
|
|
|
next_node = topo->N1;
|
|
|
}
|
|
|
- else if (type == GV_BOUNDARY) {
|
|
|
+ else if (ltype == GV_BOUNDARY) {
|
|
|
struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[-last]->topo;
|
|
|
+
|
|
|
next_node = topo->N1;
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
- if (type == GV_LINE) {
|
|
|
+ if (ltype == GV_LINE) {
|
|
|
struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[last]->topo;
|
|
|
+
|
|
|
next_node = topo->N2;
|
|
|
}
|
|
|
- else if (type == GV_BOUNDARY) {
|
|
|
+ else if (ltype == GV_BOUNDARY) {
|
|
|
struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[last]->topo;
|
|
|
+
|
|
|
next_node = topo->N2;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
Vect_reset_list(List);
|
|
|
while (1) {
|
|
|
- Vect_list_append(List, last);
|
|
|
+ G_ilist_add(List, last);
|
|
|
node_n_lines = Vect_get_node_n_lines(Map, next_node);
|
|
|
- same_type = 0;
|
|
|
+ lines_type = 0;
|
|
|
next_line = last;
|
|
|
for (i = 0; i < node_n_lines; i++) {
|
|
|
curr_line = Vect_get_node_line(Map, next_node, i);
|
|
|
- if ((Plus->Line[abs(curr_line)]->type & type)) {
|
|
|
- same_type++;
|
|
|
- if (abs(curr_line) != abs(last))
|
|
|
- next_line = curr_line;
|
|
|
+ if ((Plus->Line[abs(curr_line)]->type & GV_LINES))
|
|
|
+ lines_type++;
|
|
|
+ if ((Plus->Line[abs(curr_line)]->type == ltype)) {
|
|
|
+ if (abs(curr_line) != abs(last)) {
|
|
|
+ Vect_read_line(Map, NULL, Cats, abs(curr_line));
|
|
|
+
|
|
|
+ if (compare_cats(MCats, Cats) == 0)
|
|
|
+ next_line = curr_line;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (same_type == 2 && abs(next_line) != abs(last) &&
|
|
|
+ if (lines_type == 2 && abs(next_line) != abs(last) &&
|
|
|
abs(next_line) != abs(first)) {
|
|
|
last = next_line;
|
|
|
|
|
|
if (last < 0) {
|
|
|
- if (type == GV_LINE) {
|
|
|
+ if (ltype == GV_LINE) {
|
|
|
struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[-last]->topo;
|
|
|
+
|
|
|
next_node = topo->N1;
|
|
|
}
|
|
|
- else if (type == GV_BOUNDARY) {
|
|
|
+ else if (ltype == GV_BOUNDARY) {
|
|
|
struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[-last]->topo;
|
|
|
+
|
|
|
next_node = topo->N1;
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
- if (type == GV_LINE) {
|
|
|
+ if (ltype == GV_LINE) {
|
|
|
struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[last]->topo;
|
|
|
+
|
|
|
next_node = topo->N2;
|
|
|
}
|
|
|
- else if (type == GV_BOUNDARY) {
|
|
|
+ else if (ltype == GV_BOUNDARY) {
|
|
|
struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[last]->topo;
|
|
|
+
|
|
|
next_node = topo->N2;
|
|
|
}
|
|
|
}
|
|
@@ -216,26 +274,21 @@ int Vect_merge_lines(struct Map_info *Map, int type, int *new_lines,
|
|
|
if (List->n_values > 1) {
|
|
|
G_debug(3, "merge %d lines", List->n_values);
|
|
|
Vect_reset_line(MPoints);
|
|
|
- Vect_reset_cats(MCats);
|
|
|
|
|
|
for (i = 0; i < List->n_values; i++) {
|
|
|
Vect_reset_line(Points);
|
|
|
- Vect_reset_cats(Cats);
|
|
|
Vect_read_line(Map, Points, Cats, abs(List->value[i]));
|
|
|
direction = (List->value[i] < 0 ? GV_BACKWARD : GV_FORWARD);
|
|
|
Vect_append_points(MPoints, Points, direction);
|
|
|
MPoints->n_points--;
|
|
|
- for (c = 0; c < Cats->n_cats; c++) {
|
|
|
- Vect_cat_set(MCats, Cats->field[c], Cats->cat[c]);
|
|
|
- }
|
|
|
if (Err) {
|
|
|
/* write out lines/boundaries to be merged */
|
|
|
- Vect_write_line(Err, type, Points, Cats);
|
|
|
+ Vect_write_line(Err, ltype, Points, Cats);
|
|
|
}
|
|
|
Vect_delete_line(Map, abs(List->value[i]));
|
|
|
}
|
|
|
MPoints->n_points++;
|
|
|
- Vect_write_line(Map, type, MPoints, MCats);
|
|
|
+ Vect_write_line(Map, ltype, MPoints, MCats);
|
|
|
merged += List->n_values;
|
|
|
newl++;
|
|
|
}
|