Esempio n. 1
0
/* Same as path() but get start/stop from the command line (for non-interactive use)
   Hamish Bowman March 2007 */
int coor_path(struct Map_info *Map, const struct color_rgb *hcolor,
	      int be_bold, double start_x, double start_y,
	      double end_x, double end_y)
{
    int ret;
    double nx, ny, fx, fy, tx, ty, msize, maxdist;
    struct line_pnts *Points;
    int start_node, end_node;
    double fdist, tdist, cost;

    Points = Vect_new_line_struct();

    msize = 10 * (D_d_to_u_col(2.0) - D_d_to_u_col(1.0));	/* do it better */
    G_debug(1, "msize = %f\n", msize);

    /*
       x1 = D_d_to_u_col ((double)(screen_x-WDTH));
       y1 = D_d_to_u_row ((double)(screen_y-WDTH));
       x2 = D_d_to_u_col ((double)(screen_x+WDTH));
       y2 = D_d_to_u_row ((double)(screen_y+WDTH));

       x1 = fabs ( x2 - x1 );
       y1 = fabs ( y2 - y1 );

       if ( x1 > y1 ) maxdist = x1;
       else maxdist = y1;
     */

/**  maxdist = 10 pixels on the display (WDTH*2); ?
 **   ie related to zoom level ??  just use msize ?? **/
    maxdist = msize;

    G_debug(1, "Maximum distance in map units = %f\n", maxdist);


    /* Vect_find_node(): find number of nearest node, 0 if not found */
    start_node = Vect_find_node(Map, start_x, start_y, 0.0, maxdist, 0);
    if (start_node > 0) {
	Vect_get_node_coor(Map, start_node, &nx, &ny, NULL);
	fprintf(stderr, _("Node %d: %f %f\n"), start_node, nx, ny);
    }
    if (start_node > 0) {
	fx = nx;
	fy = ny;
    }
    else {
	fx = start_x;
	fy = start_y;
    }
    D_RGB_color(hcolor->r, hcolor->g, hcolor->b);
    D_plot_icon(fx, fy, G_ICON_BOX, 0.0, msize);


    end_node = Vect_find_node(Map, end_x, end_y, 0.0, maxdist, 0);
    if (end_node > 0) {
	Vect_get_node_coor(Map, end_node, &nx, &ny, NULL);
	fprintf(stderr, _("Node %d: %f %f\n"), end_node, nx, ny);
    }
    if (end_node > 0) {
	tx = nx;
	ty = ny;
    }
    else {
	tx = end_x;
	ty = end_y;
    }
    D_RGB_color(hcolor->r, hcolor->g, hcolor->b);
    D_plot_icon(tx, ty, G_ICON_CROSS, 0.0, msize);


    G_debug(2, "find path %f %f -> %f %f", fx, fy, tx, ty);

    ret =
	Vect_net_shortest_path_coor(Map, fx, fy, 0.0, tx, ty, 0.0,
				    5 * maxdist, 5 * maxdist, &cost, Points,
				    NULL, NULL, NULL, NULL, &fdist, &tdist);
    if (ret == 0) {
	fprintf(stdout, _("Destination unreachable\n"));
    }
    else {
	fprintf(stdout, _("Costs on the network = %f\n"), cost);
	fprintf(stdout, _("  Distance to the network = %f, "
			  "distance from the network = %f\n\n"),
		fdist, tdist);

	display(Map, Points, hcolor, 1, 1, be_bold);
    }

    return 0;
}
Esempio n. 2
0
int
bar(double cx, double cy, int size, double scale, double *val, int ncols,
    COLOR * ocolor, COLOR * colors, int y_center, double *max_reference,
    int do3d)
{
    int i;
    double max;
    double x0, y0, x1, y1, dx, dy;
    double bw;			/* bar width */
    double pixel;		/* pixel size */
    struct line_pnts *Points, *max_Points;

    G_debug(4, "bar(): cx = %f cy = %f", cx, cy);

    Points = Vect_new_line_struct();
    max_Points = Vect_new_line_struct();

    pixel = D_d_to_u_col(2) - D_d_to_u_col(1);	/* do it better */

    /* Bottom (y0) */
    max = 0;
    for (i = 0; i < ncols; i++) {
	if (val[i] > max)
	    max = val[i];
    }

    /* debug */
    /* printf("%f \n", max_reference); */

    if (y_center == 0)
	/* draw the columns with the bottom at the y value of the point  */
	y0 = cy;
    else
	/* center the columns around the y value of the point */
	y0 = cy - scale * max * pixel / 2;

    /* Left (x0) */
    x0 = cx - size * pixel / 2;

    bw = size * pixel / ncols;
    dx = bw / 5.0;
    dy = dx * 1.5;

    if (max_reference) {
	/* Draw polygon outlining max value in dataset with no fill color */
	for (i = 0; i < ncols; i++) {
	    Vect_reset_line(max_Points);
	    Vect_append_point(max_Points, x0 + i * bw, y0, 0);
	    Vect_append_point(max_Points, x0 + (i + 1) * bw, y0, 0);
	    Vect_append_point(max_Points, x0 + (i + 1) * bw,
			      y0 + scale * max_reference[i] * pixel, 0);
	    Vect_append_point(max_Points, x0 + i * bw,
			      y0 + scale * max_reference[i] * pixel, 0);
	    Vect_append_point(max_Points, x0 + i * bw, y0, 0);

	    /* the outline color : default is black */
	    D_RGB_color(ocolor->r, ocolor->g, ocolor->b);
	    D_polyline_abs(max_Points->x, max_Points->y, max_Points->n_points);
	}
    }

    /* Draw polygon for each value */
    for (i = 0; i < ncols; i++) {
	Vect_reset_line(Points);
	Vect_append_point(Points, x0 + i * bw, y0, 0);
	Vect_append_point(Points, x0 + (i + 1) * bw, y0, 0);
	Vect_append_point(Points, x0 + (i + 1) * bw,
			  y0 + scale * val[i] * pixel, 0);
	Vect_append_point(Points, x0 + i * bw, y0 + scale * val[i] * pixel,
			  0);
	Vect_append_point(Points, x0 + i * bw, y0, 0);

	if (!colors[i].none) {
	    D_RGB_color(colors[i].r, colors[i].g, colors[i].b);
	    D_polygon_abs(Points->x, Points->y, Points->n_points);
	}

	D_RGB_color(ocolor->r, ocolor->g, ocolor->b);
	D_polyline_abs(Points->x, Points->y, Points->n_points);
	
	if (do3d) {
	    /* up */
	    Vect_reset_line(Points);
	    y1 = y0 + scale * val[i] * pixel;
	    Vect_append_point(Points, x0 + i * bw, y1, 0);
	    Vect_append_point(Points, x0 + i * bw + dx, y1 + dy, 0);
	    Vect_append_point(Points, x0 + (i + 1) * bw + dx, y1 + dy, 0);
	    Vect_append_point(Points, x0 + (i + 1) * bw, y1, 0);
	    Vect_append_point(Points, x0 + i * bw, y1, 0);

	    if (!colors[i].none) {
		D_RGB_color(colors[i].r, colors[i].g, colors[i].b);
		D_polygon_abs(Points->x, Points->y, Points->n_points);
	    }

	    D_RGB_color(ocolor->r, ocolor->g, ocolor->b);
	    /* do not draw the same line twice */
	    Points->n_points = 4;
	    D_polyline_abs(Points->x, Points->y, Points->n_points);

	    /* right */
	    Vect_reset_line(Points);
	    x1 = x0 + (i + 1) * bw;
	    Vect_append_point(Points, x1 + dx + 0.5 * pixel, y1 + dy, 0);
	    Vect_append_point(Points, x1 + dx + 0.5 * pixel, y0 + dy, 0);
	    Vect_append_point(Points, x1, y0, 0);
	    Vect_append_point(Points, x1, y1, 0);
	    Vect_append_point(Points, x1 + dx + 0.5 * pixel, y1 + dy, 0);

	    if (!colors[i].none && val[i] > 0) {
		D_RGB_color(colors[i].r, colors[i].g, colors[i].b);
		D_polygon_abs(Points->x, Points->y, Points->n_points);
	    }

	    D_RGB_color(ocolor->r, ocolor->g, ocolor->b);
	    /* do not draw the same line twice */
	    Points->n_points = 3;
	    D_polyline_abs(Points->x, Points->y, Points->n_points);
	}
    }

    /* tidy up */
    Vect_destroy_line_struct(Points);
    Vect_destroy_line_struct(max_Points);

    return 0;
}
Esempio n. 3
0
int draw_n_arrow(double east, double north, double rotation, char *lbl,
                 int rot_with_text, double fontsize, char *n_arrow_num,
                 double line_width)
{
    double x_pos, y_pos;
    double t, b, l, r;
    double tt, tb, tl, tr;      /* text box */

    SYMBOL *Symb;
    RGBA_Color *line_color, *fill_color;
    int R, G, B;
    double x0, y0;
    char icon[64];
    double symbol_size;


    /* Establish text size */
    if (fontsize > 0)
        D_text_size(fontsize, fontsize);

    D_setup_unity(0);
    D_get_src(&t, &b, &l, &r);

    x_pos = l + (int)(east * (r - l) / 100.);
    y_pos = t + (int)((100. - north) * (b - t) / 100.);

    if (line_width > 0)
        D_line_width(line_width);

    if (fontsize > 0) {
        /* draw the label (default "N") */
        if (rot_with_text)
            D_text_rotation(rotation * 180.0 / M_PI);
        D_get_text_box(lbl, &tt, &tb, &tl, &tr);
        D_use_color(text_color);

        /* positions manually tuned */
        switch (n_arrow_num[0]) {
        case '1':
            D_pos_abs(x_pos - sin(rotation) * 50 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 50 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '3':
            D_pos_abs(x_pos - sin(rotation) * 60 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 60 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '4':
            D_pos_abs(x_pos - sin(rotation) * 45 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 45 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '7':
            D_pos_abs(x_pos - sin(rotation) * 70 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 70 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '8':
            D_pos_abs(x_pos - sin(rotation) * 60 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 60 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '9':
            D_pos_abs(x_pos - sin(rotation) * 55 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 55 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case 'f':
            D_pos_abs(x_pos - sin(rotation) * 55 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 55 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case 'b':
            D_pos_abs(x_pos - sin(rotation) * 48.5 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 48.5 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case 'a':
            D_pos_abs(x_pos - sin(rotation) * 50 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 50 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case 's':
            D_pos_abs(x_pos - sin(rotation) * 50 - (tr + tl) / 2,
                      y_pos - cos(rotation) * 50 - (tb + tt) / 2);
            D_text(lbl);
            break;
        case '2':
        case '5':
        case '6':
            break;
        default:
            G_fatal_error(_("Could not parse symbol"));
        }
    }

    /* display the north arrow symbol */
    line_color = G_malloc(sizeof(RGBA_Color));
    fill_color = G_malloc(sizeof(RGBA_Color));

    if (D_color_number_to_RGB(fg_color, &R, &G, &B) == 0)
        line_color->a = RGBA_COLOR_TRANSPARENT;
    else
        line_color->a = RGBA_COLOR_OPAQUE;
    line_color->r = (unsigned char)R;
    line_color->g = (unsigned char)G;
    line_color->b = (unsigned char)B;


    if (D_color_number_to_RGB(bg_color, &R, &G, &B) == 0)
        fill_color->a = RGBA_COLOR_TRANSPARENT;
    else
        fill_color->a = RGBA_COLOR_OPAQUE;
    fill_color->r = (unsigned char)R;
    fill_color->g = (unsigned char)G;
    fill_color->b = (unsigned char)B;

    /* sizes manually tuned */
    switch (n_arrow_num[0]) {
    case '1':
        symbol_size = 35.;
        break;
    case '2':
        symbol_size = 19.;
        break;
    case '3':
        symbol_size = 20.;
        break;
    case '4':
        symbol_size = 15.;
        break;
    case '5':
    case '6':
        symbol_size = 14.;
        break;
    case '7':
        symbol_size = 23.;
        break;
    case '8':
    case '9':
        symbol_size = 17.;
        break;
    case 'b':
        symbol_size = 80.;
        break;
    case 'f':
        symbol_size = 100.;
        break;
    case 'a':
        if (n_arrow_num[5] == '2')
            symbol_size = 53.;
        else
            symbol_size = 70.;
        break;
    case 's':
        symbol_size = 80.;
        break;
    default:
        G_fatal_error(_("Could not parse symbol"));
    }

    x0 = D_d_to_u_col(x_pos);
    y0 = D_d_to_u_row(y_pos);

    if (n_arrow_num[0] == 'b')
        strcpy(icon, "n_arrows/basic_compass");
    else if (n_arrow_num[0] == 'f')
        strcpy(icon, "n_arrows/fancy_compass");
    else if (n_arrow_num[0] == 'a' && n_arrow_num[5] == '1')
        strcpy(icon, "basic/arrow1");
    else if (n_arrow_num[0] == 'a' && n_arrow_num[5] == '2')
        strcpy(icon, "basic/arrow2");
    else if (n_arrow_num[0] == 'a' && n_arrow_num[5] == '3')
        strcpy(icon, "basic/arrow3");
    else if (n_arrow_num[0] == 's')
        strcpy(icon, "extra/4pt_star");
    else {
        strcpy(icon, "n_arrows/n_arrow");
        strncat(icon, n_arrow_num, 32);
    }

    Symb = S_read(icon);

    if (!Symb)
        G_fatal_error(_("Could not read symbol \"%s\""), icon);

    S_stroke(Symb, symbol_size, rotation * (180 / M_PI), 0);
    D_symbol(Symb, x0, y0, line_color, fill_color);


    if (line_width > 0)
        D_line_width(0);

    G_free(Symb);
    G_free(line_color);
    G_free(fill_color);

    return 0;
}
Esempio n. 4
0
int move_line_update(void *closure, int sxn, int syn, int button)
{
    struct move_line *ml = closure;
    double x = D_d_to_u_col(sxn);
    double y = D_d_to_u_row(syn);

    G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y);

    if (ml->last_line > 0) {
	display_line(ml->last_line, SYMB_DEFAULT, 1);
    }

    if (button == 3)
	return 1;

    if (button == 1) {		/* Select / new location */
	int type;

	if (ml->last_line == 0) {	/* Select line */
	    ml->line =
		Vect_find_line(&Map, x, y, 0, GV_POINT | GV_CENTROID,
			       ml->thresh, 0, 0);
	    G_debug(2, "point found = %d", ml->line);
	    if (ml->line == 0)
		ml->line =
		    Vect_find_line(&Map, x, y, 0, GV_LINE | GV_BOUNDARY,
				   ml->thresh, 0, 0);
	    G_debug(2, "line found = %d", ml->line);

	    /* Display new selected line if any */
	    if (ml->line > 0) {
		display_line(ml->line, SYMB_HIGHLIGHT, 1);

		/* Find the nearest point on the line */
		type = Vect_read_line(&Map, ml->Points, NULL, ml->line);
		Vect_line_distance(ml->Points, x, y, 0, 0, &ml->xo, &ml->yo,
				   NULL, NULL, NULL, NULL);
		set_location(D_u_to_d_col(ml->xo), D_u_to_d_row(ml->yo));

		i_prompt_buttons(_("New location"), _("Unselect"), _("Quit tool"));
	    }
	    ml->last_line = ml->line;
	}
	else {			/* Line is already selected */
	    int node1, node2;
	    int i;

	    display_line(ml->last_line, SYMB_BACKGROUND, 1);
	    Vect_get_line_nodes(&Map, ml->last_line, &node1, &node2);
	    display_node(node1, SYMB_BACKGROUND, 1);
	    display_node(node2, SYMB_BACKGROUND, 1);

	    type = Vect_read_line(&Map, ml->Points, ml->Cats, ml->last_line);
	    for (i = 0; i < ml->Points->n_points; i++) {
		ml->Points->x[i] = ml->Points->x[i] + x - ml->xo;
		ml->Points->y[i] = ml->Points->y[i] + y - ml->yo;
	    }

	    Vect_rewrite_line(&Map, ml->last_line, type, ml->Points,
			      ml->Cats);

	    updated_lines_and_nodes_erase_refresh_display();
	    ml->last_line = 0;
	}

    }
    if (button == 2) {		/* Unselect */
	if (ml->last_line > 0) {
	    ml->last_line = 0;
	}
    }

    if (ml->last_line == 0) {
	i_prompt_buttons(_("Select"), "", _("Quit tool"));
	set_mode(MOUSE_POINT);
    }
    else
	set_mode(MOUSE_LINE);

    return 0;
}
Esempio n. 5
0
int delete_line_update(void *closure, int sxn, int syn, int button)
{
    struct delete_line *dl = closure;
    double x = D_d_to_u_col(sxn);
    double y = D_d_to_u_row(syn);

    G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y);

    /* Display last highlighted in normal color */
    if (dl->last_line > 0) {
	display_line(dl->last_line, SYMB_DEFAULT, 1);
    }

    if (button == 3)		/* Quit tool */
	return 1;

    if (button == 1) {		/* Confirm / select */
	/* Delete last if any */
	if (dl->last_line > 0) {
	    int node1, node2;
	    int i;

	    /* Erase line and nodes !!! (because if the line is not connected to any other, nodes will die */
	    display_line(dl->last_line, SYMB_BACKGROUND, 1);
	    Vect_get_line_nodes(&Map, dl->line, &node1, &node2);
	    G_debug(2, "delete line = %d node1 = %d node2 = %d",
		    dl->last_line, node1, node2);

	    display_node(node1, SYMB_BACKGROUND, 1);
	    display_node(node2, SYMB_BACKGROUND, 1);

	    Vect_read_line(&Map, NULL, dl->Cats, dl->last_line);
	    Vect_delete_line(&Map, dl->last_line);
	    for (i = 0; i < dl->Cats->n_cats; i++) {
		check_record(dl->Cats->field[i], dl->Cats->cat[i]);
	    }

	    for (i = 0; i < Vect_get_num_updated_lines(&Map); i++)
		G_debug(2, "Updated line: %d",
			Vect_get_updated_line(&Map, i));

	    for (i = 0; i < Vect_get_num_updated_nodes(&Map); i++)
		G_debug(2, "Updated node: %d",
			Vect_get_updated_node(&Map, i));

	    updated_lines_and_nodes_erase_refresh_display();
	}

	/* Find neares point or line */
	dl->line =
	    Vect_find_line(&Map, x, y, 0, GV_POINT | GV_CENTROID, dl->thresh,
			   0, 0);
	G_debug(2, "point found = %d", dl->line);
	if (dl->line == 0)
	    dl->line =
		Vect_find_line(&Map, x, y, 0, GV_LINE | GV_BOUNDARY,
			       dl->thresh, 0, 0);
	G_debug(2, "line found = %d", dl->line);

	/* Display new selected line if any */
	if (dl->line > 0) {
	    display_line(dl->line, SYMB_HIGHLIGHT, 1);
	}
    }
    else {			/* button == 2 -> unselect */
	dl->line = 0;
    }

    if (dl->line > 0)
	i_prompt_buttons(_("Confirm and select next"), _("Unselect"), _("Quit tool"));
    else
	i_prompt_buttons(_("Select"), _("Unselect"), _("Quit tool"));

    dl->last_line = dl->line;
    dl->first = 0;

    return 0;
}
Esempio n. 6
0
int edit_line_update(void *closure, int sxn, int syn, int button)
{
    struct edit_line *el = closure;
    double x = D_d_to_u_col(sxn);
    double y = D_d_to_u_row(syn);

    G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y);

    if (button == 3)		/* Tool broken by GUI */
	return 1;

    switch (el->phase) {
    case 1:
	if (button != 1)
	    return 0;

	/* Find nearest point or line */
	el->line =
	    Vect_find_line(&Map, x, y, 0, GV_LINE | GV_BOUNDARY, el->thresh,
			   0, 0);
	G_debug(2, "line found = %d", el->line);

	/* Display new selected line if any */
	if (el->line > 0) {
	    display_line(el->line, SYMB_HIGHLIGHT, 1);
	    edit_line_phase2(el, x, y);
	}
	break;

    case 2:
	if (button == 1) {	/* New point */
	    snap(&x, &y);
	    Vect_append_point(el->Points, x, y, 0);

	    if (el->line_type == GV_LINE)
		symb_set_driver_color(SYMB_LINE);
	    else
		symb_set_driver_color(SYMB_BOUNDARY_0);

	    display_points(el->Points, 1);
	    set_location(sxn, syn);
	    i_prompt_buttons(_("New Point"), _("Undo Last Point"), _("Close line"));
	}
	else if (button == 2) {	/* Undo last point */
	    if (el->Points->n_points > 1) {
		symb_set_driver_color(SYMB_BACKGROUND);
		display_points(el->Points, 1);

		el->Points->n_points--;

		if (el->line_type == GV_LINE)
		    symb_set_driver_color(SYMB_LINE);
		else
		    symb_set_driver_color(SYMB_BOUNDARY_0);

		display_points(el->Points, 1);
		set_location(D_u_to_d_col
			     (el->Points->x[el->Points->n_points - 1]),
			     D_u_to_d_row(el->Points->
					  y[el->Points->n_points - 1])
		    );
		if (el->Points->n_points == 1)
		    i_prompt_buttons(_("New Point"), "", _("Delete line and exit"));
	    }
	}
	break;
    }

    return 0;
}
Esempio n. 7
0
int new_line_update(void *closure, int sxn, int syn, int button)
{
    struct new_line *nl = closure;
    double x = D_d_to_u_col(sxn);
    double y = D_d_to_u_row(syn);
    double dist;

    G_debug(3, "button = %d x = %d = %f y = %d = %f", button, sxn, x, syn, y);

    if (nl->first && button == 3) {	/* Quit tool ( points & lines ), first is always for points */
	Tool_next = TOOL_NOTHING;
	return 1;
    }
    
    if (button > 3) /* Do nothing on mouse scroll */ 
        return 0; 

    if (nl->type & GV_POINTS && (button == 1 ||  button == 2)) {
	snap(&x, &y);
	Vect_append_point(nl->Points, x, y, 0);

	write_line(&Map, nl->type, nl->Points);
	updated_lines_and_nodes_erase_refresh_display();
	return 1;
    }
    else {			/* GV_LINES */
	/* Button may be 1,2,3 */
	if (button == 1) {	/* New point */
	    if (snap(&x, &y) == 0) {
		/* If not snapping to other features, try to snap to lines start.
		 * Allows to create area of single boundary. */
		if (nl->Points->n_points > 2) {
		    dist = Vect_points_distance(nl->Points->x[0], nl->Points->y[0], 0, x, y, 0, WITHOUT_Z);
		    if (dist < get_thresh()) {
			x = nl->Points->x[0];
			y = nl->Points->y[0];
		    }
		}
	    }
	    if (Vect_append_point(nl->Points, x, y, 0) == -1) {
		G_warning(_("Out of memory! Point not added."));
		return 0;
	    }

	    if (nl->type == GV_LINE)
		symb_set_driver_color(SYMB_LINE);
	    else
		symb_set_driver_color(SYMB_BOUNDARY_0);

	    display_points(nl->Points, 1);
	    set_location(D_u_to_d_col(x), D_u_to_d_row(y));
	    nl->first = 0;
	    set_mode(MOUSE_LINE);
	}
	else if (button == 2) {	/* Undo last point */
	    if (nl->Points->n_points >= 1) {
		symb_set_driver_color(SYMB_BACKGROUND);
		display_points(nl->Points, 1);
		nl->Points->n_points--;

		if (nl->type == GV_LINE)
		    symb_set_driver_color(SYMB_LINE);
		else
		    symb_set_driver_color(SYMB_BOUNDARY_0);

		display_points(nl->Points, 1);
		set_location(D_u_to_d_col
			     (nl->Points->x[nl->Points->n_points - 1]),
			     D_u_to_d_row(nl->Points->
					  y[nl->Points->n_points - 1])
		    );
	    }
	    if (nl->Points->n_points == 0) {
		i_prompt_buttons(_("New point"), "", _("Quit tool"));
		nl->first = 1;
		set_mode(MOUSE_POINT);
	    }
	}
	else if (button == 3) {		/* write the line and quit */
	    if (nl->Points->n_points > 1) {
		/* Before the line is written, we must check if connected to existing nodes, if yes,
		 * such nodes must be add to update list before! the line is written (areas/isles */
		int node1 =
		    Vect_find_node(&Map, nl->Points->x[0], nl->Points->y[0],
				   nl->Points->z[0], 0, Vect_is_3d(&Map));
		int i = nl->Points->n_points - 1;
		int node2 =
		    Vect_find_node(&Map, nl->Points->x[i], nl->Points->y[i],
				   nl->Points->z[i], 0, Vect_is_3d(&Map));

		G_debug(2, "  old node1 = %d  old node2 = %d", node1, node2);
		write_line(&Map, nl->type, nl->Points);
		updated_lines_and_nodes_erase_refresh_display();
	    }
	    else
		G_warning(_("Less than 2 points for line -> nothing written"));

	    return 1;
	}
	G_debug(2, "n_points = %d", nl->Points->n_points);
    }

    i_prompt_buttons(_("New point"), _("Undo last point"), _("Close line"));
    return 0;
}