~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to vector/v.overlay/line_area.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *
3
3
 *  MODULE: v.overlay 
4
4
 *
5
 
 *  AUTHOR(S): Radim Blazek
 
5
 *  AUTHOR(S): Radim Blazek, Markus Metz
6
6
 *  
7
7
 ******************************************************************************/
8
8
#include <stdlib.h>
10
10
#include <stdio.h>
11
11
#include <grass/gis.h>
12
12
#include <grass/dbmi.h>
13
 
#include <grass/Vect.h>
 
13
#include <grass/vector.h>
14
14
#include <grass/glocale.h>
15
15
#include "local.h"
16
16
 
 
17
/* compare category structures
 
18
 * return 0 identical
 
19
 * return 1 not identical
 
20
 */
 
21
static int compare_cats(struct line_cats *ACats, struct line_cats *BCats)
 
22
{
 
23
    int i, j;
 
24
 
 
25
    if (ACats->n_cats == 0 || BCats->n_cats == 0) {
 
26
        if (ACats->n_cats == 0 && BCats->n_cats == 0)
 
27
            return 0;
 
28
 
 
29
        if (ACats->n_cats == 0 && BCats->n_cats > 0)
 
30
            return 1;
 
31
 
 
32
        if (ACats->n_cats > 0 && BCats->n_cats == 0)
 
33
            return 1;
 
34
    }
 
35
 
 
36
    for (i = 0; i < ACats->n_cats; i++) {
 
37
        int found = 0;
 
38
 
 
39
        for (j = 0; j < BCats->n_cats; j++) {
 
40
            if (ACats->cat[i] == BCats->cat[j] &&
 
41
                ACats->field[i] == BCats->field[j]) {
 
42
                found = 1;
 
43
                break;
 
44
            }
 
45
        }
 
46
        if (!found)
 
47
            return 1;
 
48
    }
 
49
    
 
50
    return 0;
 
51
}
 
52
 
 
53
/* merge a given line with all other lines of the same type and 
 
54
 * with the same categories */
 
55
static int merge_line(struct Map_info *Map, int line,
 
56
                      struct line_pnts *MPoints, struct line_cats *MCats)
 
57
{
 
58
    int nlines, i, first, last, next_line, curr_line;
 
59
    int merged = 0, newl = 0;
 
60
    int next_node, direction, node_n_lines, type, ltype, lines_type;
 
61
    static struct ilist *List = NULL;
 
62
    static struct line_pnts *Points = NULL;
 
63
    static struct line_cats *Cats = NULL;
 
64
    type = GV_LINE;
 
65
 
 
66
    nlines = Vect_get_num_lines(Map);
 
67
 
 
68
    if (!Points)
 
69
        Points = Vect_new_line_struct();
 
70
    if (!Cats)
 
71
        Cats = Vect_new_cats_struct();
 
72
    if (!List)
 
73
        List = Vect_new_list();
 
74
 
 
75
    Vect_reset_line(Points);
 
76
    Vect_reset_cats(Cats);
 
77
    Vect_reset_cats(MCats);
 
78
    Vect_reset_list(List);
 
79
 
 
80
    if (!Vect_line_alive(Map, line))
 
81
        return 0;
 
82
 
 
83
    ltype = Vect_get_line_type(Map, line);
 
84
 
 
85
    if (!(ltype & type))
 
86
        return 0;
 
87
        
 
88
    Vect_read_line(Map, MPoints, MCats, line);
 
89
 
 
90
    /* special cases:
 
91
     *  - loop back to start boundary via several other boundaries
 
92
     *  - one boundary forming closed loop
 
93
     *  - node with 3 entries but only 2 boundaries, one of them connecting twice,
 
94
     *    the other one must then be topologically incorrect in case of boundary */
 
95
 
 
96
    /* go backward as long as there is only one other line/boundary at the current node */
 
97
    G_debug(3, "go backward");
 
98
    Vect_get_line_nodes(Map, line, &next_node, NULL);
 
99
 
 
100
    first = -line;
 
101
    while (1) {
 
102
        node_n_lines = Vect_get_node_n_lines(Map, next_node);
 
103
        /* count lines/boundaries at this node */
 
104
        lines_type = 0;
 
105
        next_line = first;
 
106
        for (i = 0; i < node_n_lines; i++) {
 
107
            curr_line = Vect_get_node_line(Map, next_node, i);
 
108
            if ((Vect_get_line_type(Map, abs(curr_line)) & GV_LINES))
 
109
                lines_type++;
 
110
            if ((Vect_get_line_type(Map, abs(curr_line)) == ltype)) {
 
111
                if (abs(curr_line) != abs(first)) {
 
112
                    Vect_read_line(Map, NULL, Cats, abs(curr_line));
 
113
                    
 
114
                    /* catgories must be identical */
 
115
                    if (compare_cats(MCats, Cats) == 0)
 
116
                        next_line = curr_line;
 
117
                }
 
118
            }
 
119
        }
 
120
        if (lines_type == 2 && abs(next_line) != abs(first) &&
 
121
            abs(next_line) != line) {
 
122
            first = next_line;
 
123
 
 
124
            if (first < 0) {
 
125
                Vect_get_line_nodes(Map, -first, &next_node, NULL);
 
126
            }
 
127
            else {
 
128
                Vect_get_line_nodes(Map, first, NULL, &next_node);
 
129
            }
 
130
        }
 
131
        else
 
132
            break;
 
133
    }
 
134
 
 
135
    /* go forward as long as there is only one other line/boundary at the current node */
 
136
    G_debug(3, "go forward");
 
137
 
 
138
    /* reverse direction */
 
139
    last = -first;
 
140
 
 
141
    if (last < 0) {
 
142
        Vect_get_line_nodes(Map, -last, &next_node, NULL);
 
143
    }
 
144
    else {
 
145
        Vect_get_line_nodes(Map, last, NULL, &next_node);
 
146
    }
 
147
 
 
148
    Vect_reset_list(List);
 
149
    while (1) {
 
150
        G_ilist_add(List, last);
 
151
        node_n_lines = Vect_get_node_n_lines(Map, next_node);
 
152
        lines_type = 0;
 
153
        next_line = last;
 
154
        for (i = 0; i < node_n_lines; i++) {
 
155
            curr_line = Vect_get_node_line(Map, next_node, i);
 
156
            if ((Vect_get_line_type(Map, abs(curr_line)) & GV_LINES))
 
157
                lines_type++;
 
158
            if ((Vect_get_line_type(Map, abs(curr_line)) == ltype)) {
 
159
                if (abs(curr_line) != abs(last)) {
 
160
                    Vect_read_line(Map, NULL, Cats, abs(curr_line));
 
161
                    
 
162
                    if (compare_cats(MCats, Cats) == 0)
 
163
                        next_line = curr_line;
 
164
                }
 
165
            }
 
166
        }
 
167
 
 
168
        if (lines_type == 2 && abs(next_line) != abs(last) &&
 
169
            abs(next_line) != abs(first)) {
 
170
            last = next_line;
 
171
 
 
172
            if (last < 0) {
 
173
                Vect_get_line_nodes(Map, -last, &next_node, NULL);
 
174
            }
 
175
            else {
 
176
                Vect_get_line_nodes(Map, last, NULL, &next_node);
 
177
            }
 
178
        }
 
179
        else
 
180
            break;
 
181
    }
 
182
 
 
183
    /* merge lines */
 
184
    G_debug(3, "merge %d lines", List->n_values);
 
185
    Vect_reset_line(MPoints);
 
186
 
 
187
    for (i = 0; i < List->n_values; i++) {
 
188
        Vect_reset_line(Points);
 
189
        Vect_read_line(Map, Points, Cats, abs(List->value[i]));
 
190
        direction = (List->value[i] < 0 ? GV_BACKWARD : GV_FORWARD);
 
191
        Vect_append_points(MPoints, Points, direction);
 
192
        MPoints->n_points--;
 
193
        Vect_delete_line(Map, abs(List->value[i]));
 
194
    }
 
195
    MPoints->n_points++;
 
196
    merged += List->n_values;
 
197
    newl++;
 
198
 
 
199
    return merged;
 
200
}
 
201
 
17
202
/* Check if point is inside area with category of given field. All cats are set in 
18
203
 * Cats with original field.
19
204
 * returns number of cats.
49
234
    return Cats->n_cats;
50
235
}
51
236
 
52
 
int line_area(struct Map_info *In, int *field, struct Map_info *Out,
53
 
              struct field_info *Fi, dbDriver * driver, int operator,
54
 
              int *ofield, ATTRIBUTES * attr, struct ilist *BList)
 
237
int line_area(struct Map_info *In, int *field, struct Map_info *Tmp,
 
238
              struct Map_info *Out, struct field_info *Fi,
 
239
              dbDriver * driver, int operator, int *ofield,
 
240
              ATTRIBUTES * attr, struct ilist *BList)
55
241
{
56
242
    int line, nlines, ncat;
57
243
    struct line_pnts *Points;
67
253
    db_init_string(&stmt);
68
254
 
69
255
    G_message(_("Breaking lines..."));
70
 
    Vect_break_lines_list(Out, NULL, BList, GV_LINE | GV_BOUNDARY, NULL);
 
256
    Vect_break_lines_list(Tmp, NULL, BList, GV_LINE | GV_BOUNDARY, NULL);
 
257
 
 
258
    /*
71
259
    G_message(_("Merging lines..."));
72
 
    Vect_merge_lines(Out, GV_LINE, NULL, NULL);
 
260
    Vect_merge_lines(Tmp, GV_LINE, NULL, NULL);
 
261
    */
73
262
 
74
 
    nlines = Vect_get_num_lines(Out);
 
263
    nlines = Vect_get_num_lines(Tmp);
75
264
 
76
265
    /* Warning!: cleaning process (break) creates new vertices which are usually slightly 
77
266
     * moved (RE), to compare such new vertex with original input is a problem?
87
276
 
88
277
        G_percent(line, nlines, 1);     /* must be before any continue */
89
278
 
90
 
        if (!Vect_line_alive(Out, line))
 
279
        if (!Vect_line_alive(Tmp, line))
91
280
            continue;
92
281
 
93
 
        ltype = Vect_read_line(Out, Points, Cats, line);
 
282
        ltype = Vect_get_line_type(Tmp, line);
94
283
 
95
284
        if (ltype == GV_BOUNDARY) {     /* No more needed */
96
 
            Vect_delete_line(Out, line);
97
285
            continue;
98
286
        }
99
287
 
112
300
         */
113
301
 
114
302
        /* Note/TODO: the test done is quite simple, check the point in the middle of segment.
115
 
         * If the line overpals the boundary, the result may be both outside and inside
 
303
         * If the line overlaps the boundary, the result may be both outside and inside
116
304
         * this should be solved (check angles?)
 
305
         * This should not happen if Vect_break_lines_list() works correctly
117
306
         */
118
307
 
 
308
        /* merge here */
 
309
        merge_line(Tmp, line, Points, Cats);
 
310
 
119
311
        G_debug(3, "line = %d", line);
120
312
 
121
313
        point_area(&(In[1]), field[1], (Points->x[0] + Points->x[1]) / 2,
239
431
                }
240
432
            }
241
433
 
242
 
            Vect_rewrite_line(Out, line, ltype, Points, OCats);
243
 
        }
244
 
        else {
245
 
            Vect_delete_line(Out, line);
 
434
            Vect_write_line(Out, ltype, Points, OCats);
246
435
        }
247
436
    }
248
437