5
#include <grass/Vect.h>
6
#include <grass/dbmi.h>
7
#include <grass/raster.h>
8
#include <grass/display.h>
9
#include <grass/colors.h>
10
#include <grass/form.h>
11
#include <grass/glocale.h>
18
struct line_pnts *Points, *NPoints;
19
struct line_cats *Cats;
20
int last_line, last_seg;
25
int split_line_begin(void *closure)
27
struct split_line *sl = closure;
29
G_debug(2, "split_line()");
31
sl->Points = Vect_new_line_struct();
32
sl->NPoints = Vect_new_line_struct();
33
sl->Cats = Vect_new_cats_struct();
35
i_prompt(_("Split line:"));
36
i_prompt_buttons(_("Select"), "", _("Quit tool"));
38
sl->thresh = get_thresh();
39
G_debug(2, "thresh = %f", sl->thresh);
44
set_mode(MOUSE_POINT);
49
int split_line_update(void *closure, int sxn, int syn, int button)
51
struct split_line *sl = closure;
52
double x = D_d_to_u_col(sxn);
53
double y = D_d_to_u_row(syn);
55
if (sl->last_line == 0) {
56
i_prompt_buttons(_("Select"), "", _("Quit tool"));
59
if (sl->last_line > 0) {
60
display_line(sl->last_line, SYMB_DEFAULT, 1);
63
G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y);
68
if (button == 1) { /* Select / split */
71
if (sl->last_line > 0) { /* Line is already selected -> split */
72
int node1, node2, type, np, i;
74
display_line(sl->last_line, SYMB_BACKGROUND, 1);
75
Vect_get_line_nodes(&Map, sl->last_line, &node1, &node2);
76
display_node(node1, SYMB_BACKGROUND, 1);
77
display_node(node2, SYMB_BACKGROUND, 1);
78
symb_set_driver_color(SYMB_BACKGROUND);
79
display_icon(sl->xo, sl->yo, G_ICON_CROSS, 0, 10, 1);
81
/* Read and delete old */
82
type = Vect_read_line(&Map, sl->Points, sl->Cats, sl->last_line);
83
Vect_delete_line(&Map, sl->last_line);
84
updated_lines_and_nodes_erase_refresh_display();
85
np = sl->Points->n_points;
88
Vect_reset_line(sl->NPoints);
89
for (i = 0; i < sl->last_seg; i++) {
90
Vect_append_point(sl->NPoints, sl->Points->x[i],
91
sl->Points->y[i], sl->Points->z[i]);
93
Vect_append_point(sl->NPoints, sl->xo, sl->yo, 0);
94
Vect_write_line(&Map, type, sl->NPoints, sl->Cats);
95
updated_lines_and_nodes_erase_refresh_display();
98
Vect_reset_line(sl->NPoints);
99
Vect_append_point(sl->NPoints, sl->xo, sl->yo, 0);
100
for (i = sl->last_seg; i < np; i++) {
101
Vect_append_point(sl->NPoints, sl->Points->x[i],
102
sl->Points->y[i], sl->Points->z[i]);
104
Vect_write_line(&Map, type, sl->NPoints, sl->Cats);
105
updated_lines_and_nodes_erase_refresh_display();
112
Vect_find_line(&Map, x, y, 0, GV_LINE | GV_BOUNDARY, sl->thresh,
114
G_debug(2, "line found = %d", line);
116
/* Display new selected line if any */
120
/* Find the nearest vertex on the line */
121
Vect_read_line(&Map, sl->Points, NULL, line);
123
Vect_line_distance(sl->Points, x, y, 0, 0, &sl->xo, &sl->yo,
124
NULL, NULL, NULL, NULL);
126
display_line(line, SYMB_HIGHLIGHT, 1);
127
symb_set_driver_color(SYMB_HIGHLIGHT);
128
display_icon(sl->xo, sl->yo, G_ICON_CROSS, 0, 10, 1);
130
i_prompt_buttons(_("Confirm and select next"), _("Unselect"),
132
sl->last_line = line;
136
if (button == 2) { /* Unselect */
137
if (sl->last_line > 0) {
138
symb_set_driver_color(SYMB_BACKGROUND);
139
display_icon(sl->xo, sl->yo, G_ICON_CROSS, 0, 10, 1);
147
int split_line_end(void *closure)
149
struct split_line *sl = closure;
151
if (sl->last_line == 0) {
152
i_prompt_buttons(_("Select"), "", _("Quit tool"));
155
if (sl->last_line > 0) {
156
display_line(sl->last_line, SYMB_DEFAULT, 1);
159
if (sl->last_line > 0) {
160
symb_set_driver_color(SYMB_BACKGROUND);
161
display_icon(sl->xo, sl->yo, G_ICON_CROSS, 0, 10, 1);
165
i_prompt_buttons("", "", "");
166
i_coor(COOR_NULL, COOR_NULL);
168
G_debug(3, "split_line(): End");
173
void split_line(void)
175
static struct split_line sl;
177
set_tool(split_line_begin, split_line_update, split_line_end, &sl);
180
/* Remove line vertex */
183
struct line_pnts *Points;
184
struct line_cats *Cats;
185
int last_line, last_seg;
190
int rm_vertex_begin(void *closure)
192
struct rm_vertex *rv = closure;
194
G_debug(2, "remove_vertex()");
196
rv->Points = Vect_new_line_struct();
197
rv->Cats = Vect_new_cats_struct();
199
i_prompt(_("Remove vertex:"));
200
i_prompt_buttons(_("Select vertex"), "", _("Quit tool"));
202
rv->thresh = get_thresh();
203
G_debug(2, "thresh = %f", rv->thresh);
208
set_mode(MOUSE_POINT);
213
int rm_vertex_update(void *closure, int sxn, int syn, int button)
215
struct rm_vertex *rv = closure;
216
double x = D_d_to_u_col(sxn);
217
double y = D_d_to_u_row(syn);
219
if (rv->last_line == 0) {
220
i_prompt_buttons(_("Select vertex"), "", _("Quit tool"));
223
if (rv->last_line > 0) {
224
display_line(rv->last_line, SYMB_DEFAULT, 1);
227
G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y);
232
if (button == 1) { /* Select / new location */
235
if (rv->last_line > 0) { /* Line is already selected */
236
int node1, node2, type, np, i;
238
display_line(rv->last_line, SYMB_BACKGROUND, 1);
239
Vect_get_line_nodes(&Map, rv->last_line, &node1, &node2);
240
display_node(node1, SYMB_BACKGROUND, 1);
241
display_node(node2, SYMB_BACKGROUND, 1);
242
symb_set_driver_color(SYMB_BACKGROUND);
243
display_icon(rv->xo, rv->yo, G_ICON_BOX, 0, 10, 1);
245
type = Vect_read_line(&Map, rv->Points, rv->Cats, rv->last_line);
246
np = rv->Points->n_points;
248
/* Lines should have at least two vertices (start and end node). */
249
if (np < 3 && Vect_line_alive(&Map, rv->last_line)) {
250
Vect_delete_line(&Map, rv->last_line);
251
for (i = 0; i < rv->Cats->n_cats; i++) {
252
check_record(rv->Cats->field[i], rv->Cats->cat[i]);
255
for (i = rv->last_seg; i < np - 1; i++) {
256
rv->Points->x[i] = rv->Points->x[i + 1];
257
rv->Points->y[i] = rv->Points->y[i + 1];
258
rv->Points->z[i] = rv->Points->z[i + 1];
260
rv->Points->n_points--;
261
Vect_rewrite_line(&Map, rv->last_line, type, rv->Points,
264
updated_lines_and_nodes_erase_refresh_display();
270
Vect_find_line(&Map, x, y, 0, GV_LINE | GV_BOUNDARY, rv->thresh,
272
G_debug(2, "line found = %d", line);
274
/* Display new selected line if any */
279
/* Find the nearest vertex on the line */
280
Vect_read_line(&Map, rv->Points, NULL, line);
282
Vect_line_distance(rv->Points, x, y, 0, 0, &rv->xo, &rv->yo,
283
NULL, NULL, NULL, NULL);
286
Vect_points_distance(rv->xo, rv->yo, 0,
287
rv->Points->x[seg - 1],
288
rv->Points->y[seg - 1], 0, 0);
291
Vect_points_distance(rv->xo, rv->yo, 0, rv->Points->x[seg],
292
rv->Points->y[seg], 0, 0)) {
296
rv->xo = rv->Points->x[seg];
297
rv->yo = rv->Points->y[seg];
299
display_line(line, SYMB_HIGHLIGHT, 1);
300
symb_set_driver_color(SYMB_HIGHLIGHT);
301
display_icon(rv->xo, rv->yo, G_ICON_BOX, 0, 10, 1);
303
i_prompt_buttons(_("Confirm and select next"), _("Unselect"),
305
rv->last_line = line;
309
if (button == 2) { /* Unselect */
310
if (rv->last_line > 0) {
311
symb_set_driver_color(SYMB_BACKGROUND);
312
display_icon(rv->xo, rv->yo, G_ICON_BOX, 0, 10, 1);
320
int rm_vertex_end(void *closure)
322
struct rm_vertex *rv = closure;
324
if (rv->last_line == 0) {
325
i_prompt_buttons(_("Select vertex"), "", _("Quit tool"));
328
if (rv->last_line > 0) {
329
display_line(rv->last_line, SYMB_DEFAULT, 1);
332
if (rv->last_line > 0) {
333
symb_set_driver_color(SYMB_BACKGROUND);
334
display_icon(rv->xo, rv->yo, G_ICON_BOX, 0, 10, 1);
338
i_prompt_buttons("", "", "");
339
i_coor(COOR_NULL, COOR_NULL);
341
G_debug(3, "remove_vertex(): End");
348
static struct rm_vertex rv;
350
set_tool(rm_vertex_begin, rm_vertex_update, rm_vertex_end, &rv);
353
/* Add new vertex to line */
356
struct line_pnts *Points;
357
struct line_cats *Cats;
358
int last_line, last_seg;
363
int add_vertex_begin(void *closure)
365
struct add_vertex *av = closure;
367
G_debug(2, "add_vertex()");
369
av->Points = Vect_new_line_struct();
370
av->Cats = Vect_new_cats_struct();
372
i_prompt(_("Add vertex:"));
373
i_prompt_buttons(_("Select"), "", _("Quit tool"));
375
av->thresh = get_thresh();
376
G_debug(2, "thresh = %f", av->thresh);
382
set_mode(MOUSE_POINT);
387
int add_vertex_update(void *closure, int sxn, int syn, int button)
389
struct add_vertex *av = closure;
390
double x = D_d_to_u_col(sxn);
391
double y = D_d_to_u_row(syn);
393
G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y);
398
if (av->last_line > 0) {
399
display_line(av->last_line, SYMB_DEFAULT, 1);
402
if (button == 1) { /* Select line segment */
403
if (av->last_line == 0) { /* Select line */
404
int line = Vect_find_line(&Map, x, y, 0, GV_LINE | GV_BOUNDARY,
407
G_debug(2, "line found = %d", line);
409
/* Display new selected line if any */
412
double xo, yo, px, py;
415
display_line(line, SYMB_HIGHLIGHT, 1);
417
/* Find the nearest vertex on the line */
418
Vect_read_line(&Map, av->Points, NULL, line);
420
Vect_line_distance(av->Points, x, y, 0, 0, &px, &py, NULL,
423
G_debug(3, "seg = %d", seg);
425
xo = (av->Points->x[seg - 1] + av->Points->x[seg]) / 2;
426
yo = (av->Points->y[seg - 1] + av->Points->y[seg]) / 2;
428
/* If close to first or last point insert before / after the line.
429
* 'close' is here < 1/4 of segment length */
433
Vect_points_distance(px, py, 0, av->Points->x[0],
434
av->Points->y[0], 0, 0);
436
Vect_points_distance(av->Points->x[0],
439
av->Points->y[1], 0, 0);
441
if (dist < len / 4) {
443
xo = av->Points->x[0];
444
yo = av->Points->y[0];
449
if (seg == av->Points->n_points - 1) {
450
int np = av->Points->n_points;
452
Vect_points_distance(px, py, 0, av->Points->x[np - 1],
453
av->Points->y[np - 1], 0, 0);
454
int len = Vect_points_distance(av->Points->x[np - 2],
455
av->Points->y[np - 2], 0,
456
av->Points->x[np - 1],
457
av->Points->y[np - 1], 0,
460
if (dist < len / 4) {
462
xo = av->Points->x[np - 1];
463
yo = av->Points->y[np - 1];
467
G_debug(3, "seg 2 = %d", seg);
469
set_location(D_u_to_d_col(xo), D_u_to_d_row(yo));
471
i_prompt_buttons(_("New vertex"), _("Unselect"), _("Quit tool"));
472
av->last_line = line;
476
else { /* Line is already selected -> new vertex */
477
int node1, node2, type, np, i;
482
display_line(av->last_line, SYMB_BACKGROUND, 1);
483
Vect_get_line_nodes(&Map, av->last_line, &node1, &node2);
484
display_node(node1, SYMB_BACKGROUND, 1);
485
display_node(node2, SYMB_BACKGROUND, 1);
487
type = Vect_read_line(&Map, av->Points, av->Cats, av->last_line);
488
np = av->Points->n_points;
490
Vect_append_point(av->Points, 0, 0, 0);
491
for (i = np; i > av->last_seg; i--) {
492
av->Points->x[i] = av->Points->x[i - 1];
493
av->Points->y[i] = av->Points->y[i - 1];
494
av->Points->z[i] = av->Points->z[i - 1];
497
av->Points->x[av->last_seg] = x;
498
av->Points->y[av->last_seg] = y;
499
av->Points->z[av->last_seg] = 0;
501
Vect_rewrite_line(&Map, av->last_line, type, av->Points,
503
updated_lines_and_nodes_erase_refresh_display();
509
if (button == 2) { /* Unselect */
510
if (av->last_line > 0) {
515
if (av->last_line == 0) {
516
i_prompt_buttons(_("Select"), "", _("Quit tool"));
517
set_mode(MOUSE_POINT);
520
set_mode(MOUSE_LINE);
525
int add_vertex_end(void *closure)
527
struct add_vertex *av = closure;
529
if (av->last_line > 0) {
530
display_line(av->last_line, SYMB_DEFAULT, 1);
534
i_prompt_buttons("", "", "");
535
i_coor(COOR_NULL, COOR_NULL);
537
G_debug(3, "add_vertex(): End");
542
void add_vertex(void)
544
static struct add_vertex av;
546
set_tool(add_vertex_begin, add_vertex_update, add_vertex_end, &av);
553
struct line_pnts *Points;
554
struct line_cats *Cats;
555
int last_line, last_seg;
560
int move_vertex_begin(void *closure)
562
struct move_vertex *mv = closure;
564
G_debug(2, "move_vertex()");
566
mv->Points = Vect_new_line_struct();
567
mv->Cats = Vect_new_cats_struct();
569
i_prompt(_("Move vertex:"));
570
i_prompt_buttons(_("Select"), "", _("Quit tool"));
572
mv->thresh = get_thresh();
573
G_debug(2, "thresh = %f", mv->thresh);
578
set_mode(MOUSE_POINT);
583
int move_vertex_update(void *closure, int sxn, int syn, int button)
585
struct move_vertex *mv = closure;
586
double x = D_d_to_u_col(sxn);
587
double y = D_d_to_u_row(syn);
589
G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y);
591
if (mv->last_line > 0) {
592
display_line(mv->last_line, SYMB_DEFAULT, 1);
598
if (button == 1) { /* Select / new location */
599
if (mv->last_line == 0) { /* Select line */
600
int line = Vect_find_line(&Map, x, y, 0, GV_POINT | GV_LINE | GV_BOUNDARY,
603
G_debug(2, "line found = %d", line);
605
/* Display new selected line if any */
610
display_line(line, SYMB_HIGHLIGHT, 1);
612
/* Find the nearest vertex on the line */
613
Vect_read_line(&Map, mv->Points, NULL, line);
615
Vect_line_distance(mv->Points, x, y, 0, 0, &xo, &yo, NULL,
619
Vect_points_distance(xo, yo, 0, mv->Points->x[seg - 1],
620
mv->Points->y[seg - 1], 0, 0);
623
Vect_points_distance(xo, yo, 0, mv->Points->x[seg],
624
mv->Points->y[seg], 0, 0)) {
628
mv->xo = mv->Points->x[seg];
629
mv->yo = mv->Points->y[seg];
630
set_location(D_u_to_d_col(mv->xo), D_u_to_d_row(mv->yo));
633
i_prompt_buttons(_("New location"), _("Unselect"), _("Quit tool"));
634
mv->last_line = line;
638
else { /* Line is already selected */
639
int type, node1, node2;
641
if (mv->last_seg == 0 || mv->last_seg == mv->Points->n_points - 1) {
644
display_line(mv->last_line, SYMB_BACKGROUND, 1);
645
Vect_get_line_nodes(&Map, mv->last_line, &node1, &node2);
646
display_node(node1, SYMB_BACKGROUND, 1);
647
display_node(node2, SYMB_BACKGROUND, 1);
649
type = Vect_read_line(&Map, mv->Points, mv->Cats, mv->last_line);
650
mv->Points->x[mv->last_seg] =
651
mv->Points->x[mv->last_seg] + x - mv->xo;
652
mv->Points->y[mv->last_seg] =
653
mv->Points->y[mv->last_seg] + y - mv->yo;
654
Vect_rewrite_line(&Map, mv->last_line, type, mv->Points,
656
updated_lines_and_nodes_erase_refresh_display();
661
if (button == 2) { /* Unselect */
662
if (mv->last_line > 0) {
668
if (mv->last_line == 0) {
669
i_prompt_buttons(_("Select"), "", _("Quit tool"));
670
set_mode(MOUSE_POINT);
673
set_mode(MOUSE_LINE);
678
int move_vertex_end(void *closure)
680
struct move_vertex *mv = closure;
682
if (mv->last_line > 0) {
683
display_line(mv->last_line, SYMB_DEFAULT, 1);
687
i_prompt_buttons("", "", "");
688
i_coor(COOR_NULL, COOR_NULL);
690
G_debug(3, "move_vertex(): End");
695
void move_vertex(void)
697
static struct move_vertex mv;
699
set_tool(move_vertex_begin, move_vertex_update, move_vertex_end, &mv);