/* * FIG : Facility for Interactive Generation of figures * Copyright (c) 1985-1988 by Supoj Sutanthavibul * Parts Copyright (c) 1989-2002 by Brian V. Smith * Parts Copyright (c) 1991 by Paul King * * Any party obtaining a copy of these files is granted, free of charge, a * full and unrestricted irrevocable, world-wide, paid up, royalty-free, * nonexclusive right and license to deal in this software and documentation * files (the "Software"), including without limitation the rights to use, * copy, modify, merge, publish distribute, sublicense and/or sell copies of * the Software, and to permit persons who receive copies from any such * party to do so, with the only requirement being that the above copyright * and this permission notice remain intact. */ /********************** DECLARATIONS ********************/ /* IMPORTS */ #include "fig.h" #include "resources.h" #include "mode.h" #include "object.h" #include "paintop.h" #include "d_arc.h" #include "u_create.h" #include "u_elastic.h" #include "u_list.h" #include "w_canvas.h" #include "w_cursor.h" #include "w_drawprim.h" #include "w_msgpanel.h" #include "w_mousefun.h" #include "u_geom.h" #include "f_util.h" #include "u_draw.h" #include "u_free.h" #include "u_markers.h" #include "u_redraw.h" /* EXPORT */ F_pos point[3]; F_pos center_point; Boolean center_marked; /* LOCAL */ static void create_arcobject(int lx, int ly); static void get_arcpoint(int x, int y); static void init_arc_drawing(int x, int y); static void cancel_arc(void); static void init_arc_c_drawing(int x, int y); static void resizing_arc(int x, int y); static F_arc *tmparc = 0; static F_pos tpoint[3]; static Boolean save_shownums; void arc_drawing_selected(void) { center_marked = FALSE; set_mousefun("first point", "center point", "", "", "", ""); canvas_kbd_proc = null_proc; canvas_locmove_proc = null_proc; canvas_leftbut_proc = init_arc_drawing; canvas_middlebut_proc = init_arc_c_drawing; canvas_rightbut_proc = null_proc; set_cursor(crosshair_cursor); reset_action_on(); } static void init_arc_drawing(int x, int y) { int i; if (center_marked) { /* erase the circle */ elastic_cbr(); /* save and turn off showing vertex numbers */ save_shownums = appres.shownums; appres.shownums = False; set_mousefun("direction", "", "cancel", "", "", ""); tmparc = create_arc(); tmparc->thickness = 1; tmparc->center.x = center_point.x; tmparc->center.y = center_point.y; /* initialize points in elastic arc */ for (i=0; i<3; i++) { tpoint[i].x = x; tpoint[i].y = y; } /* start the arc */ elastic_arc(); canvas_locmove_proc = resizing_arc; } else { set_mousefun("mid point", "", "cancel", "", "", ""); } draw_mousefun_canvas(); canvas_rightbut_proc = cancel_arc; point[0].x = fix_x = cur_x = x; point[0].y = fix_y = cur_y = y; num_point = 1; if (!center_marked) { canvas_locmove_proc = unconstrained_line; elastic_line(); } canvas_leftbut_proc = get_arcpoint; canvas_middlebut_proc = null_proc; set_cursor(null_cursor); set_action_on(); } static void init_arc_c_drawing(int x, int y) { set_mousefun("first point", "", "cancel", "", "", ""); draw_mousefun_canvas(); canvas_locmove_proc = resizing_cbr; canvas_middlebut_proc = null_proc; canvas_rightbut_proc = cancel_arc; center_point.x = fix_x = cur_x = x; center_point.y = fix_y = cur_y = y; center_marked = TRUE; center_marker(center_point.x, center_point.y); set_action_on(); num_point = 0; } static void cancel_arc(void) { if (center_marked) { /* erase circle */ if (num_point == 0) elastic_cbr(); else elastic_arc(); /* free the temporary arc */ if (tmparc) { free_arc(&tmparc); tmparc = (F_arc *) 0; } center_marked = FALSE; center_marker(center_point.x, center_point.y); /* clear center marker */ /* restore shownums */ appres.shownums = save_shownums; } else { /* erase any length info if appres.showlengths is true */ erase_lengths(); elastic_line(); if (num_point == 2) { /* erase initial part of line */ cur_x = point[0].x; cur_y = point[0].y; elastic_line(); } } arc_drawing_selected(); draw_mousefun_canvas(); } static void get_arcpoint(int x, int y) { if (x == fix_x && y == fix_y) return; if (num_point == 1) { if (center_marked) { set_mousefun("final angle", "", "cancel", "", "", ""); } else { set_mousefun("final point", "", "cancel", "", "", ""); } draw_mousefun_canvas(); canvas_leftbut_proc = create_arcobject; } if (!center_marked) elastic_line(); cur_x = x; cur_y = y; if (!center_marked) elastic_line(); point[num_point].x = fix_x = x; point[num_point++].y = fix_y = y; if (!center_marked) elastic_line(); } static void create_arcobject(int lx, int ly) { F_arc *arc; int x, y; float xx, yy; /* erase last line segment */ if (!center_marked) elastic_line(); else /* restore shownums */ appres.shownums = save_shownums; /* erase any length info if appres.showlengths is true */ erase_lengths(); point[num_point].x = lx; point[num_point++].y = ly; x = point[0].x; y = point[0].y; if (center_marked) { double theta, r; /* erase the center marker */ center_marker(center_point.x, center_point.y); /* free the temporary arc */ free_arc(&tmparc); /* recompute the second and last points to put them on the arc */ r = sqrt((double)(point[0].x - center_point.x) * (point[0].x - center_point.x) + (double)(point[0].y - center_point.y) * (point[0].y - center_point.y)); theta = compute_angle((double)(point[1].x - center_point.x), (double)(point[1].y - center_point.y)); point[1].x = center_point.x + r * cos(theta); point[1].y = center_point.y + r * sin(theta); theta = compute_angle((double)(point[2].x - center_point.x), (double)(point[2].y - center_point.y)); point[2].x = center_point.x + r * cos(theta); point[2].y = center_point.y + r * sin(theta); } else { /* erase previous line segment */ pw_vector(canvas_win, x, y, point[1].x, point[1].y, INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT); } if (!compute_arccenter(point[0], point[1], point[2], &xx, &yy)) { put_msg("Invalid ARC geometry"); beep(); arc_drawing_selected(); draw_mousefun_canvas(); return; } if ((arc = create_arc()) == NULL) { arc_drawing_selected(); draw_mousefun_canvas(); return; } arc->type = cur_arctype; arc->style = cur_linestyle; arc->thickness = cur_linewidth; /* scale dash length according to linethickness */ arc->style_val = cur_styleval * (cur_linewidth + 1) / 2; arc->pen_style = -1; arc->fill_style = cur_fillstyle; arc->pen_color = cur_pencolor; arc->fill_color = cur_fillcolor; arc->cap_style = cur_capstyle; arc->depth = cur_depth; arc->direction = compute_direction(point[0], point[1], point[2]); /* only allow arrowheads for open arc */ if (arc->type == T_PIE_WEDGE_ARC) { arc->for_arrow = NULL; arc->back_arrow = NULL; } else { if (autoforwardarrow_mode) arc->for_arrow = forward_arrow(); else arc->for_arrow = NULL; if (autobackwardarrow_mode) arc->back_arrow = backward_arrow(); else arc->back_arrow = NULL; } arc->center.x = xx; arc->center.y = yy; arc->point[0].x = point[0].x; arc->point[0].y = point[0].y; arc->point[1].x = point[1].x; arc->point[1].y = point[1].y; arc->point[2].x = point[2].x; arc->point[2].y = point[2].y; arc->next = NULL; add_arc(arc); reset_action_on(); /* this signals redisplay_curobj() not to refresh */ /* draw it and anything on top of it */ redisplay_arc(arc); arc_drawing_selected(); draw_mousefun_canvas(); } static void resizing_arc(int x, int y) { F_point p3; double alpha; elastic_arc(); cur_x = x; cur_y = y; p3.x = x; p3.y = y; if (num_point == 0) length_msg(MSG_RADIUS); else { compute_3p_angle((F_point *)&tpoint[0], (F_point *)¢er_point, &p3, &alpha); put_msg("1st angle = %.2f degrees", (float) alpha*180.0/M_PI); } elastic_arc(); } void elastic_arc(void) { register int i; register double r, theta1, theta2; tpoint[2].x = cur_x; tpoint[2].y = cur_y; /* if user hasn't entered second point yet, make it average of endpoints */ if (num_point <= 1) { tpoint[1].x = (tpoint[0].x + cur_x)/2; tpoint[1].y = (tpoint[0].y + cur_y)/2; } if (tpoint[0].x == tpoint[2].x && tpoint[0].y == tpoint[2].y) return; r = sqrt((double)(tpoint[0].x - center_point.x) * (tpoint[0].x - center_point.x) + (double)(tpoint[0].y - center_point.y) * (tpoint[0].y - center_point.y)); theta1 = compute_angle((double)(tpoint[1].x - center_point.x), (double)(tpoint[1].y - center_point.y)); tpoint[1].x = center_point.x + r * cos(theta1); tpoint[1].y = center_point.y + r * sin(theta1); theta2 = compute_angle((double)(tpoint[2].x - center_point.x), (double)(tpoint[2].y - center_point.y)); tpoint[2].x = center_point.x + r * cos(theta2); tpoint[2].y = center_point.y + r * sin(theta2); for (i=0; i<3; i++) tmparc->point[i] = tpoint[i]; tmparc->direction = compute_direction(tpoint[0], tpoint[1], tpoint[2]); draw_arc(tmparc, INV_PAINT); }