4
#include <grass/vector.h>
5
#include <grass/glocale.h>
8
static int next_dist(int line, int side, double mf)
10
double d, dist, nextdist, totaldist;
13
static struct line_pnts *Points = NULL;
15
G_debug(3, "next_dist()");
18
Points = Vect_new_line_struct();
20
Vect_read_line(&Out, Points, NULL, abs(line));
21
dist = Vect_line_length(Points);
24
Vect_get_line_nodes(&Out, -line, &node, NULL);
26
Vect_get_line_nodes(&Out, line, NULL, &node);
28
nlines = Vect_get_node_n_lines(&Out, node);
33
nextdist = totaldist = 0.;
35
nextline = dig_angle_next_line(&(Out.plus), -line, side, GV_LINE, NULL);
36
Vect_read_line(&Out, Points, NULL, abs(nextline));
37
d = Vect_line_length(Points);
42
Vect_get_line_nodes(&Out, -nextline, &node, NULL);
44
Vect_get_line_nodes(&Out, nextline, NULL, &node);
46
nlines = Vect_get_node_n_lines(&Out, node);
52
if (totaldist > nextdist && dist > nextdist)
53
return (totaldist < mf * dist);
55
return (dist > nextdist);
58
static int loop_test(int line, int node, struct line_pnts *Points,
61
int line1, line2, nextline;
62
int n1, n2, nspikes, nout;
63
double l1, minl, maxl;
65
if (Vect_get_node_n_lines(&Out, node) != 3)
69
line1 = Vect_get_node_line(&Out, node, 0);
70
if (abs(line1) == abs(line))
72
line2 = Vect_get_node_line(&Out, node, 1);
73
if (abs(line2) == abs(line))
80
line2 = Vect_get_node_line(&Out, node, 2);
82
if (abs(line1) == abs(line2))
85
nextline = dig_angle_next_line(&(Out.plus), -line, GV_LEFT, GV_LINE, NULL);
94
Vect_get_line_nodes(&Out, -nextline, &n1, NULL);
96
Vect_get_line_nodes(&Out, nextline, NULL, &n1);
98
if (Vect_get_node_n_lines(&Out, n1) == 1)
101
if (n1 != node && Vect_get_node_n_lines(&Out, n1) > 2) {
103
line2 = dig_angle_next_line(&(Out.plus), -nextline, GV_LEFT, GV_LINE, NULL);
106
Vect_get_line_nodes(&Out, -line2, &n2, NULL);
108
Vect_get_line_nodes(&Out, line2, NULL, &n2);
110
if (Vect_get_node_n_lines(&Out, n2) == 1) {
111
Vect_read_line(&Out, Points, NULL, abs(line2));
112
l1 = Vect_line_length(Points);
113
if (minl == 0 || minl > l1) {
124
nextline = dig_angle_next_line(&(Out.plus), -nextline, GV_RIGHT, GV_LINE, NULL);
126
} while (abs(nextline) != abs(line1));
136
return (nspikes < 3 || (nspikes == 3 && (l > minl || mf * l > maxl)));
140
if (nspikes == 3 && l < minl)
141
return (mf * l > maxl);
143
return (nspikes < 3);
146
return (nspikes < 3 || (nspikes > 2 && l > minl));
149
static int break_loop(int line, int node, struct line_pnts *Points)
151
int line1, line2, firstline, nextline;
155
if (Vect_get_node_n_lines(&Out, node) != 3)
159
line1 = Vect_get_node_line(&Out, node, 0);
160
if (abs(line1) == abs(line))
162
line2 = Vect_get_node_line(&Out, node, 1);
163
if (abs(line2) == abs(line))
170
line2 = Vect_get_node_line(&Out, node, 2);
172
if (abs(line1) == abs(line2))
175
nextline = dig_angle_next_line(&(Out.plus), -line, GV_LEFT, GV_LINE, NULL);
176
firstline = nextline;
180
Vect_get_line_nodes(&Out, -nextline, &n1, NULL);
182
Vect_get_line_nodes(&Out, nextline, NULL, &n1);
184
if (Vect_get_node_n_lines(&Out, n1) == 1)
187
nextline = dig_angle_next_line(&(Out.plus), -nextline, GV_RIGHT, GV_LINE, NULL);
189
} while (abs(nextline) != abs(firstline));
191
if (abs(nextline) != abs(firstline)) {
192
G_warning("no loop ???");
196
Vect_read_line(&Out, Points, NULL, abs(line1));
197
l1 = Vect_line_length(Points);
199
Vect_read_line(&Out, Points, NULL, abs(line2));
200
l2 = Vect_line_length(Points);
203
Vect_delete_line(&Out, abs(line1));
205
Vect_delete_line(&Out, abs(line2));
207
Vect_merge_lines(&Out, GV_LINE, NULL, NULL);
212
static int length_test(int line, int node, struct line_pnts *Points,
215
int line1, line2, nlines;
219
if (Vect_get_node_n_lines(&Out, node) != 3)
222
line1 = Vect_get_node_line(&Out, node, 0);
224
if (abs(line1) == abs(line))
226
line2 = Vect_get_node_line(&Out, node, 1);
227
if (abs(line2) == abs(line))
234
line2 = Vect_get_node_line(&Out, node, 2);
237
Vect_get_line_nodes(&Out, -line1, &n1, NULL);
239
Vect_get_line_nodes(&Out, line1, NULL, &n1);
241
nlines = Vect_get_node_n_lines(&Out, n1);
246
Vect_get_line_nodes(&Out, -line2, &n1, NULL);
248
Vect_get_line_nodes(&Out, line2, NULL, &n1);
250
nlines = Vect_get_node_n_lines(&Out, n1);
254
Vect_read_line(&Out, Points, NULL, abs(line1));
255
l1 = Vect_line_length(Points);
257
Vect_read_line(&Out, Points, NULL, abs(line2));
258
l2 = Vect_line_length(Points);
261
if (mf * l < l1 && l < l2)
265
if (mf * l < l2 && l < l1)
269
return (mf * l > l1 || mf * l > l2);
272
/* thin the skeletons */
273
int thin_skeleton(double thresh)
277
struct line_pnts *Points;
279
double l, minl, maxl;
280
int nlines, line, minline, line2;
282
double morphof = 1.6180339887;
284
Points = Vect_new_line_struct();
285
list = Vect_new_list();
290
Vect_merge_lines(&Out, GV_LINE, NULL, NULL);
293
G_verbose_message(_("Pass %d"), counter++);
294
Vect_reset_list(list);
296
for (node = 1; node <= Vect_get_num_nodes(&Out); node++) {
297
if (!Vect_node_alive(&Out, node))
299
nlines = Vect_get_node_n_lines(&Out, node);
304
line = Vect_get_node_line(&Out, node, 0);
306
Vect_get_line_nodes(&Out, -line, &n1, NULL);
308
Vect_get_line_nodes(&Out, line, NULL, &n1);
310
nlines = Vect_get_node_n_lines(&Out, n1);
315
Vect_read_line(&Out, Points, NULL, abs(line));
317
minl = Vect_line_length(Points);
320
if (loop_test(line, n1, Points, minl, morphof))
322
if (length_test(line, n1, Points, minl, morphof))
327
for (i = 0; i < nlines; i++) {
328
line2 = Vect_get_node_line(&Out, n1, i);
329
if (abs(line2) == abs(minline) || abs(line2) == abs(line))
332
Vect_get_line_nodes(&Out, -line2, &n2, NULL);
334
Vect_get_line_nodes(&Out, line2, NULL, &n2);
335
if (Vect_get_node_n_lines(&Out, n2) > 1)
337
Vect_read_line(&Out, Points, NULL, abs(line2));
338
l = Vect_line_length(Points);
343
if (maxl == 0 || maxl < l) {
348
G_ilist_add(list, minline);
352
G_ilist_add(list, minline);
355
if (list->n_values == 0)
358
for (i = 0; i < list->n_values; i++) {
359
line = list->value[i];
360
if (Vect_line_alive(&Out, abs(line))) {
361
if (next_dist(line, GV_RIGHT, morphof))
363
if (next_dist(line, GV_LEFT, morphof))
365
Vect_delete_line(&Out, abs(line));
372
Vect_merge_lines(&Out, GV_LINE, NULL, NULL);
378
for (node = 1; node <= Vect_get_num_nodes(&Out); node++) {
379
if (!Vect_node_alive(&Out, node))
381
nlines = Vect_get_node_n_lines(&Out, node);
386
line = Vect_get_node_line(&Out, node, 0);
388
Vect_get_line_nodes(&Out, -line, &n1, NULL);
390
Vect_get_line_nodes(&Out, line, NULL, &n1);
392
nlines = Vect_get_node_n_lines(&Out, n1);
395
break_loop(line, n1, Points);
400
G_verbose_message(_("Pass %d"), counter++);
401
Vect_reset_list(list);
403
for (node = 1; node <= Vect_get_num_nodes(&Out); node++) {
404
if (!Vect_node_alive(&Out, node))
406
nlines = Vect_get_node_n_lines(&Out, node);
411
line = Vect_get_node_line(&Out, node, 0);
413
Vect_get_line_nodes(&Out, -line, &n1, NULL);
415
Vect_get_line_nodes(&Out, line, NULL, &n1);
417
nlines = Vect_get_node_n_lines(&Out, n1);
422
Vect_read_line(&Out, Points, NULL, abs(line));
424
minl = Vect_line_length(Points);
427
if (break_loop(line, n1, Points))
431
for (i = 0; i < nlines; i++) {
432
line2 = Vect_get_node_line(&Out, n1, i);
433
if (abs(line2) == abs(minline) || abs(line2) == abs(line))
436
Vect_get_line_nodes(&Out, -line2, &n2, NULL);
438
Vect_get_line_nodes(&Out, line2, NULL, &n2);
439
if (Vect_get_node_n_lines(&Out, n2) > 1)
441
Vect_read_line(&Out, Points, NULL, abs(line2));
442
l = Vect_line_length(Points);
448
if (thresh < 0 || minl < thresh)
449
G_ilist_add(list, minline);
451
if (list->n_values == 0)
454
for (i = 0; i < list->n_values; i++) {
455
line = list->value[i];
456
if (Vect_line_alive(&Out, abs(line))) {
457
if (next_dist(line, GV_RIGHT, morphof))
459
if (next_dist(line, GV_LEFT, morphof))
461
Vect_delete_line(&Out, abs(line));
468
Vect_merge_lines(&Out, GV_LINE, NULL, NULL);
479
double xmin, ymin, x, y;
480
double dx, dy, dist, distmin;
481
struct line_pnts *Points;
482
struct line_pnts **IPoints;
483
struct line_cats *Cats;
485
int area, isle, n_isles;
488
Points = Vect_new_line_struct();
490
IPoints = G_malloc(isl_allocated * sizeof(struct line_pnts *));
491
for (i = 0; i < isl_allocated; i++)
492
IPoints[i] = Vect_new_line_struct();
493
Cats = Vect_new_cats_struct();
495
for (node = 1; node <= Vect_get_num_nodes(&Out); node++) {
496
if (!Vect_node_alive(&Out, node))
498
nlines = Vect_get_node_n_lines(&Out, node);
503
Vect_get_node_coor(&Out, node, &x, &y, NULL);
505
/* find area for this node */
506
area = Vect_find_area(&In, x, y);
509
G_fatal_error(_("Node is outside any input area"));
511
/* get area outer ring */
512
Vect_get_area_points(&In, area, Points);
514
/* get area inner rings */
515
n_isles = Vect_get_area_num_isles(&In, area);
516
if (n_isles > isl_allocated) {
517
IPoints = (struct line_pnts **)
518
G_realloc(IPoints, (1 + n_isles) * sizeof(struct line_pnts *));
519
for (i = isl_allocated; i < n_isles; i++)
520
IPoints[i] = Vect_new_line_struct();
521
isl_allocated = n_isles;
523
for (i = 0; i < n_isles; i++) {
524
Vect_get_isle_points(&In, Vect_get_area_isle(&In, area, i),
528
distmin = 1. / 0.; /* +inf */
532
/* find closest point to outer ring */
533
/* must be an existing vertex */
534
for (i = 0; i < Points->n_points - 1; i++) {
535
dx = x - Points->x[i];
536
dy = y - Points->y[i];
538
dist = dx * dx + dy * dy;
540
if (distmin > dist) {
547
/* find closest point to inner rings */
548
/* must be an existing vertex */
549
for (isle = 0; isle < n_isles; isle++) {
550
for (i = 0; i < IPoints[isle]->n_points - 1; i++) {
551
dx = x - IPoints[isle]->x[i];
552
dy = y - IPoints[isle]->y[i];
554
dist = dx * dx + dy * dy;
556
if (distmin > dist) {
558
xmin = IPoints[isle]->x[i];
559
ymin = IPoints[isle]->y[i];
564
if (xmin != x && ymin != y) {
565
Vect_get_area_cats(&In, area, Cats);
566
Vect_reset_line(Points);
567
Vect_append_point(Points, xmin, ymin, 0);
568
Vect_append_point(Points, x, y, 0);
569
Vect_write_line(&Out, GV_LINE, Points, Cats);