/* * ACE/gredit - 2d finite element grid generation * * Paul J. Turner and Antonio M. Baptista * * Copyright 1990-2003 Oregon Health and Science University * All Rights Reserved. * */ /* * canvas event proc and set_action() * */ #ifndef lint static char RCSid[] = "$Id: events.c,v 1.6 2011/09/14 17:44:21 pturner Exp $"; #endif #include #include #include "motifinc.h" #include "defines.h" #include "globals.h" #include "graphics.h" #define MOVE_WORLD1ST 997 #define MOVE_WORLD2ND 998 #define CENTER_WORLD 999 Widget mode_item; Widget locate_grid_item; Widget calc_item; Widget locate_item; /* locator on main_panel */ Widget comparea_item; Widget compperi_item; extern int go_locateflag; extern Display *disp; extern Window cwin; extern GC gc; extern GC gcxor; extern GC gcclr; extern int spreadflag; extern int cercnum; void DrawPNodeLists(int gridno); void AddToPNodeList(int nlno, int node, int ival, double dval, int color); extern int curnl; extern int curnlcolor; extern int curnlival; extern double curnldval; double area(), area_from_nodes(), get_depth_element(); void set_action(int act); static char buf[256]; static int action_flag = 0; static int call_flag = 0; static int rectflag = 0; static int rotrectflag = 0; static int rubber_flag = 0; int mbox_flag = 0; /* moving box attached to cursor */ int mline_flag = 0; /* moving line attached to cursor */ static double wx1, wx2, wy1, wy2, wx3, wy3, wx, wy; static int sx, sy, old_x, old_y; /* for rubber banding and rects */ static int sx1, sy1; /* for rotated rect rubberbanding */ static int sx2, sy2; /* for rotated rect rubberbanding */ static int sx3, sy3; /* for rotated rect rubberbanding */ static int tmpind; static int bnd1, bnd2, ind1, ind2, ind3, ind4, ind5; /* for adding elements */ static double sm, sb; /* for snap lines */ static int bnof, indf; static int n0, n1, n2, n3, n4, n5, n6, n7; extern int deltaflag; extern int pointset; double dsx, dsy; /* for 1-d slices */ extern double slicex[], slicey[]; extern int slice_npts; extern int win_h, win_w; /* * variables for the text handling routine */ static int strx = 0, stry = 0; static int drawx = 0, drawy = 0; static char tmpstr[256]; static int justflag = 0; static double si = 0.0; static double co = 1.0; static int xs, ys; static int cg = 0; void doSync(void) { XSync(disp, False); } void setpointer(int x, int y) { XWarpPointer(disp, None, cwin, 0, None, (unsigned int) win_w, (unsigned int) win_h, x, y); XFlush(disp); } /* * rubber band line */ void select_line(int x1, int y1, int x2, int y2) { XDrawLine(disp, cwin, gcxor, x1, y1, x2, y2); } /* * draw rotated box */ void select_rotated_rect(int x1, int y1, int x2, int y2, int x3, int y3) { double rot; XDrawLine(disp, cwin, gcxor, x1, y1, x2, y2); XDrawLine(disp, cwin, gcxor, x2, y2, x3, y3); XDrawLine(disp, cwin, gcxor, x3, y3, x1, y1); } /* * draw a box on the display */ void draw_rectangle(int x1, int y1, int x2, int y2) { XDrawRectangle(disp, cwin, gc, x1, y1, x2, y2); } /* * draw an xor'ed box */ void select_region(int x1, int y1, int x2, int y2) { int dx = x2 - x1; int dy = y2 - y1; if (dx < 0) { iswap(&x1, &x2); dx = -dx; } if (dy < 0) { iswap(&y1, &y2); dy = -dy; } XDrawRectangle(disp, cwin, gcxor, x1, y1, dx, dy); } /* * switch on the area calculator */ void do_select_area(void) { set_action(0); set_action(COMP_AREA); } /* * switch on the perimeter calculator */ void do_select_peri(void) { set_action(0); set_action(COMP_PERIMETER); } /* * evaluate an expression for the calculator */ void do_calc_proc(void) { static double a = 0.0; static double b = 0.0; static double c = 0.0; static double d = 0.0; static double x = 0.0; static double y = 0.0; static int errpos; static char val[128]; extern double result; errpos = 0; strcpy(val, (char *) panel_getstr_value(calc_item)); fixupstr(val); scanner(val, &x, &y, &a, &b, &c, &d, 0, 0, &errpos); if (errpos) { } else { sprintf(val, "%.5g", result); } } /* * select the type of display for locator */ void do_setdeltype(int value) { deltaflag = value; } void reset_action(void) { set_action(action_flag); } /* * set the action_flag to the desired action (actions are * defined in defines.h), if 0 then cleanup the results * from previous actions. */ void set_action(int act) { int i; extern Widget canvas; set_window(canvas); if ((action_flag = act) == 0) { /* clean up */ nibuf = 0; npoly = 0; nipoly = 0; write_mode_str("Idle ..."); if (rectflag) { select_region(sx, sy, old_x, old_y); rectflag = 0; } if (rotrectflag) { select_rotated_rect(sx1, sy1, sx2, sy2, sx3, sy3); rotrectflag = 0; } if (rubber_flag) { select_line(sx, sy, old_x, old_y); rubber_flag = 0; } if (mbox_flag) { select_region(sx, sy, xs, ys); mbox_flag = 0; } if (mline_flag) { select_line(sx, sy, xs, ys); mline_flag = 0; } set_cursor(-1); } else { switch (act) { case DEFINE_REGION: set_cursor(0); break; case SELECT_SNAP: set_cursor(0); write_mode_str("Click near nodes to snap"); break; case SNAP_LINE1ST: set_cursor(0); write_mode_str("Click at the beginning of the line to snap to"); break; case SNAP_LINE2ND: set_cursor(0); write_mode_str("Click at the end of the line to snap to"); break; case DEF_EXT_BOUND: write_mode_str("Click at a point to include into the exterior boundary"); set_cursor(0); break; case DEF_INT_BOUND: write_mode_str("Click at a point to include into an interior boundary"); set_cursor(0); break; case MOVE_EXT_BOUND1ST: write_mode_str("Click near the external boundary point to move"); set_cursor(0); break; case MOVE_EXT_BOUND2ND: write_mode_str("Click at the new location of the external boundary point"); set_cursor(0); break; case MOVE_INT_BOUND1ST: write_mode_str("Click near the internal boundary point to move"); set_cursor(0); break; case MOVE_INT_BOUND2ND: write_mode_str("Click at the new location of the internal boundary point"); set_cursor(0); break; case DEL_EXT_BOUNDPT: set_cursor(3); break; case DEL_INT_BOUNDPT: set_cursor(3); break; case DEL_INT_BOUND: set_cursor(3); break; case DEL_BOUND_PT: set_cursor(3); break; case ADD_BOUND1: set_cursor(0); write_mode_str("Click at first boundary node (CCW)"); break; case ADD_BOUND2: set_cursor(0); write_mode_str("Click at second boundary node (CCW)"); break; case ADD_BOUND3: set_cursor(0); write_mode_str("Click at location for new boundary node"); break; case ADD_BUILD1: set_cursor(0); break; case ADD_BUILD2: set_cursor(0); break; case ADD_BUILD3: set_cursor(0); break; case GENFD_1ST: set_cursor(0); write_mode_str("Click at the first point of the base line for the rectangle"); break; case GENFD_2ND: set_cursor(0); write_mode_str("Click at the end of the base line for the rectangle"); break; case GENFD_3RD: set_cursor(0); write_mode_str("Click at the point off the base line to define the rectangle"); break; case ADD_NODE_BOUND1: set_cursor(0); break; case ADD_NODE_BOUND2: set_cursor(0); break; case ADD_NODE_BOUND3: set_cursor(0); break; case PLACE_BUILD: set_cursor(0); write_mode_str("Click at a point for the new build point location"); break; case PLACE_BUILD_ARC: break; case DELETE_BUILD: set_cursor(3); write_mode_str("Click near a build point to delete (accept with the middle button, cancel with the right)"); break; case MOVE_BUILD1ST: set_cursor(0); write_mode_str("Click on a build point to move"); break; case MOVE_BUILD2ND: write_mode_str("Click at the new location of the build point"); break; case ADD_NODE: set_cursor(0); write_mode_str("Click at a point for the new node location"); break; case GET_NEAREST_NODE: write_mode_str("Click near a node"); set_cursor(1); break; case GET_NEAREST_ELEMENT: write_mode_str("Click near an element"); set_cursor(1); break; case GET_ELEMENT: write_mode_str("Click in the interior of an element"); set_cursor(1); break; case GET_GRID_DEPTH: write_mode_str("Click at a point in the interior of the edit grid"); set_cursor(0); break; case GET_BACK_DEPTH: write_mode_str("Click at a point in the interior of the background grid"); set_cursor(0); break; case GET_NEAREST_BUILDPT: write_mode_str("Click near a build point"); set_cursor(1); break; case GET_DEPTH_ALL: write_mode_str("Click near a point"); set_cursor(1); break; case GET_ALL: write_mode_str("Click at a point in the interior of the edit grid"); set_cursor(1); break; case MOVE_NODE1ST: set_cursor(0); write_mode_str("Click on a node to move"); break; case MOVE_NODE2ND: set_cursor(0); write_mode_str("Click at a point for the new position of the node"); break; case SWAPLINE_1ST: set_cursor(0); write_mode_str("Click on one element with shared line to swap"); break; case SWAPLINE_2ND: set_cursor(0); write_mode_str("Click on adjacent element with shared line to swap"); break; case CUT_GRID1ST: set_cursor(0); break; case CUT_GRID2ND: set_cursor(0); break; case ADD_ELEMENT1: set_cursor(0); write_mode_str("Click on the first node (add nodes in a counterclockwise fashion)"); break; case ADD_ELEMENT2: set_cursor(0); write_mode_str("Click on the second node"); break; case ADD_ELEMENT3: set_cursor(0); write_mode_str("Click on the third node"); break; case DELETE_ELEMENT: set_cursor(3); write_mode_str("Click near the element to delete (accept with middle button, cancel with right)"); break; case DELETE_ELEMENTS: set_cursor(3); write_mode_str("Click in the interior of the element to delete (accept with middle button, cancel with right)"); break; case SPLIT_ELEMENT3: set_cursor(0); write_mode_str("Click on elements to split in 3"); break; case SPLIT_ELEMENT4: set_cursor(0); write_mode_str("Click on elements to split in 4"); break; case SPLIT_ELEMENTS3: set_cursor(0); break; case SPLIT_ELEMENTS4: set_cursor(0); break; case ZOOM_1ST: set_cursor(0); write_mode_str("Click on one corner of a rectangle to enlarge"); break; case ZOOM_2ND: set_cursor(0); write_mode_str("Click on the opposite corner of rectangle to enlarge"); break; case COMP_AREA: set_cursor(0); break; case COMP_PERIMETER: set_cursor(0); break; case SEL_POINT: set_cursor(0); break; case PICK_NODE_LIST: write_mode_str("Click on a node to add to the current list of nodes"); set_cursor(0); break; /* case PICK_ELEMENT_LIST: set_cursor(0); break; */ case PICK_ISTOK: set_cursor(0); break; case PICK_PROP_NODE: write_mode_str("Click on a node to set the nodal property"); set_cursor(0); break; case PICK_PROP_ELEM: write_mode_str("Click on an element to set the elemental property"); set_cursor(0); break; case QUERY_PROP_ELEM: write_mode_str("Click on an element to get the elemental property"); set_cursor(0); break; case PLACE_GRIDBATH_LEGEND: write_mode_str("Click at the location of the legend"); set_cursor(0); break; case PLACE_BACKBATH_LEGEND: write_mode_str("Click at the location of the legend"); set_cursor(0); break; case PLACE_CONC_LEGEND: write_mode_str("Click at the location of the legend"); set_cursor(0); break; case DEL_OBJECT: set_cursor(3); write_mode_str("Delete object"); break; case MOVE_OBJECT_1ST: set_cursor(4); write_mode_str("Pick object"); break; case MOVE_OBJECT_2ND: write_mode_str("Place object"); break; case MAKE_BOX_1ST: set_cursor(0); write_mode_str("First corner of box"); break; case MAKE_BOX_2ND: write_mode_str("Second corner of box"); break; case STR_LOC1ST: set_cursor(0); write_mode_str("Pick start of text line"); break; case STR_LOC2ND: write_mode_str("Pick end of text line"); break; case MAKE_LINE_1ST: set_cursor(0); write_mode_str("Pick beginning of line"); break; case MAKE_LINE_2ND: write_mode_str("Pick end of line"); break; case STR_EDIT: set_cursor(2); write_mode_str("Edit string"); break; case STR_LOC: set_cursor(2); write_mode_str("Pick beginning of text"); break; case EXTRACT_GRID: set_cursor(0); write_mode_str("Define a region of the edit grid to extract"); break; case PLACE_VSCALE: set_cursor(0); write_mode_str("Click at a point for the gradient scale"); break; case ADD_QUAD1: set_cursor(0); write_mode_str("Click near the 1st node of the quadrangular element"); break; case ADD_QUAD2: set_cursor(0); write_mode_str("Click near the 2nd node of the quadrangular element"); break; case ADD_QUAD3: set_cursor(0); write_mode_str("Click near the 3rd node of the quadrangular element"); break; case ADD_QUAD4: set_cursor(0); write_mode_str("Click near the 4th node of the quadrangular element"); break; case CONV_4TO3: set_cursor(0); write_mode_str("Click inside the quadrangle to convert to 2 triangles"); break; case CONV_3TO4_1ST: set_cursor(0); write_mode_str("Click inside the first triangle"); break; case CONV_3TO4_2ND: set_cursor(0); write_mode_str("Click inside the second triangle (must share an edge with the first)"); break; case EDIT_NODE: set_cursor(0); write_mode_str("Click near the node to edit"); break; case CONV_NODE2COL: set_cursor(0); write_mode_str("Click near the node to convert to 3 colocated nodes"); break; case ADD_NODELIST: case ADD_BCNODELIST: set_cursor(0); write_mode_str("Click near node to add to the current list of nodes"); break; case ADD_BCNODELIST1ST: case ADD_NODELIST1ST: set_cursor(0); write_mode_str("Click near the starting node"); break; case ADD_BCNODELIST2ND: case ADD_NODELIST2ND: set_cursor(0); write_mode_str("Click near the ending node"); break; case DELETE_NODE: set_cursor(3); write_mode_str("Click near the node to delete"); break; case PLACE_ISOLINE_LABEL: set_cursor(0); write_mode_str("Click at a point in the grid to place a label"); break; case PLACE_ISOLINES_LEGEND: set_cursor(0); write_mode_str("Click on the location of the top of the legend"); break; case VIEW_1ST: set_cursor(0); write_mode_str("Pick first corner of viewport"); break; case VIEW_2ND: write_mode_str("Pick second corner of viewport"); break; case OPENB1ST: set_cursor(0); write_mode_str("Select starting open boundary node"); break; case OPENB2ND: set_cursor(0); write_mode_str("Select ending open boundary node"); break; case LANDB1ST: set_cursor(0); write_mode_str("Select starting land boundary node"); break; case LANDB2ND: set_cursor(0); write_mode_str("Select ending land boundary node"); break; default: break; } } } /* * draw a cursor for text writing * TODO: fix the rotation problems (cursor doesn't track) */ void update_text_cursor(char *s, int x, int y) { int hgt, tx, xtx, ytx, xhgt, yhgt; hgt = stringextenty(charsize * xlibcharsize, "N") / 2; tx = stringextentx(charsize * xlibcharsize, s); xtx = (int) tx *co; ytx = (int) tx *si; xhgt = (int) -hgt * si; yhgt = (int) hgt *co; /* select_line(x + tx, win_h - y + hgt, x + tx, win_h - y - hgt); */ select_line(x + xtx + xhgt, win_h - (y + ytx + yhgt), x + xtx - xhgt, win_h - (y + ytx - yhgt)); } /* * update string drawn on the canvas */ void do_text_string(int op, int c) { char stmp[2]; drawx = strx; drawy = stry; update_text_cursor(tmpstr, drawx, drawy); set_write_mode(0); dispstrxlib(drawx, drawy, string_rot, tmpstr, justflag, 0); switch (op) { case 0: if (strlen(tmpstr) > 0) { tmpstr[strlen(tmpstr) - 1] = 0; } break; case 1: sprintf(stmp, "%c", c); strcat(tmpstr, stmp); break; case 2: break; } set_write_mode(1); dispstrxlib(drawx, drawy, string_rot, tmpstr, justflag, 0); update_text_cursor(tmpstr, drawx, drawy); } /* * canvas event proc */ void my_proc(Widget w, caddr_t data, XEvent * event) { static int x, y, boxno, lineno, ox, oy; static double wx1, wx2, wy1, wy2; static double wx, wy, dx, dy; static int ty, no, c; static KeySym keys; static XComposeStatus compose; extern Widget canvas; double xconv(), yconv(); /* * hot keys */ x = event->xmotion.x; y = event->xmotion.y; switch (event->type) { case KeyPress: buf[0] = 0; XLookupString((XKeyEvent *) event, buf, 1, &keys, &compose); switch (c = buf[0]) { case 1: /* ^A */ break; case 2: /* ^B */ break; case 3: /* ^C */ set_action(0); set_action(CENTER_WORLD); break; case 4: /* ^D */ break; case 5: /* ^E */ break; case 6: /* ^F */ break; case 7: /* ^G */ break; /* stay off 8 (^H) - needed by text routines */ case 12: /* ^L */ break; case 14: /* ^N */ break; case 16: /* ^P */ break; case 18: /* ^R */ break; case 19: /* ^S */ break; case 20: /* ^T */ break; case 22: /* ^V */ break; case 23: /* ^W */ set_action(0); set_action(MOVE_WORLD1ST); break; case 24: /* ^X */ break; case 26: /* ^Z */ set_action(0); set_action(ZOOM_1ST); break; case 27: /* ESC cancel any operation */ set_action(0); break; case 8: case 127: if (action_flag == STR_LOC) { do_text_string(0, 0); } break; case '\r': case '\n': if (action_flag == STR_LOC) { int itmp; update_text_cursor(tmpstr, drawx, drawy); if (tmpstr[0]) { device2world(drawx, win_h - drawy, &wx, &wy); define_string(tmpstr, wx, wy); } itmp = (int) (1.25 * stringextenty(charsize * xlibcharsize, "Ny")); strx = strx + si * itmp; stry = stry - co * itmp; tmpstr[0] = 0; update_text_cursor(tmpstr, strx, stry); } break; default: if (action_flag == STR_LOC) { if (c >= 32 && c < 128) { do_text_string(1, c); } } break; } break; case EnterNotify: set_window(w); defineworld(xg1, yg1, xg2, yg2, 0, 0); viewport(0.0, 0.0, 1.0, 1.0); break; case LeaveNotify: break; case ButtonRelease: switch (event->xbutton.button) { case Button1: break; case Button2: break; case Button3: break; } break; case ButtonPress: switch (event->xbutton.button) { case Button3: switch (action_flag) { case COMP_AREA: case COMP_PERIMETER: if (nipoly >= 3) { int i; for (i = 0; i < nipoly; i++) { } } break; case EXTRACT_GRID: case DEF_EXT_BOUND: case DEF_INT_BOUND: npoly = 0; nipoly = 0; break; case SELECT_SNAP: case DELETE_BUILD: case DELETE_ELEMENTS: case DELETE_ELEMENT: case DELETE_NODE: nibuf = 0; break; case DEFINE_REGION: nregion = 0; region_flag = 0; break; default: break; } npoly = 0; nipoly = 0; nibuf = 0; slice_npts = 0; set_action(0); break; case Button1: c = go_locateflag; go_locateflag = TRUE; getpoints(x, y); go_locateflag = c; switch (action_flag) { case DEL_OBJECT: /* delete a box or a line */ set_action(0); device2world(x, y, &wx, &wy); find_item(cg, wx, wy, &ty, &no); if (ty >= 0) { switch (ty) { case BOX: set_write_mode(0); draw_box(-2, no); set_write_mode(1); kill_box(no); break; case LINE: set_write_mode(0); draw_line(-2, no); set_write_mode(1); kill_line(no); break; case STRING: set_write_mode(0); draw_string(-2, no); set_write_mode(1); kill_string(no); break; } } break; /* * select a box or a line to move */ case MOVE_OBJECT_1ST: set_action(MOVE_OBJECT_2ND); device2world(x, y, &wx, &wy); /* ZZZZ */ find_item(cg, wx, wy, &ty, &no); if (ty < 0) { set_action(0); } else { switch (ty) { case BOX: if (boxes[no].loctype == VIEW) { sx = (int) (win_w * boxes[no].x1); sy = (int) (win_h - win_h * boxes[no].y1); xs = (int) (win_w * boxes[no].x2); ys = (int) (win_h - win_h * boxes[no].y2); } else { world2deviceabs(boxes[no].x1, boxes[no].y1, &sx, &sy); world2deviceabs(boxes[no].x2, boxes[no].y2, &xs, &ys); } select_region(sx, sy, xs, ys); mbox_flag = 1; break; case LINE: if (lines[no].loctype == VIEW) { sx = (int) (win_w * lines[no].x1); sy = (int) (win_h - win_h * lines[no].y1); xs = (int) (win_w * lines[no].x2); ys = (int) (win_h - win_h * lines[no].y2); } else { world2deviceabs(lines[no].x1, lines[no].y1, &sx, &sy); world2deviceabs(lines[no].x2, lines[no].y2, &xs, &ys); } select_line(sx, sy, xs, ys); mline_flag = 1; break; case STRING: xs = stringextentx(charsize * xlibcharsize, pstr[no].s); ys = stringextenty(charsize * xlibcharsize, pstr[no].s); if (pstr[no].loctype == VIEW) { sx = (int) (win_w * pstr[no].x); sy = (int) (win_h - win_h * pstr[no].y); } else { world2device(pstr[no].x, pstr[no].y, &sx, &sy); } xs = sx + xs; ys = sy + ys; mbox_flag = 1; select_region(sx, sy, xs, ys); break; } } break; /* * box has been selected and new position found */ case MOVE_OBJECT_2ND: dx = sx - x; dy = sy - y; set_action(0); sx = x; sy = y; xs = xs - dx; ys = ys - dy; device2world(sx, sy, &wx1, &wy1); device2world(xs, ys, &wx2, &wy2); switch (ty) { case BOX: set_write_mode(0); draw_box(-2, no); if (boxes[no].loctype == VIEW) { wx1 = xconv(wx1); wy1 = yconv(wy1); wx2 = xconv(wx2); wy2 = yconv(wy2); } else { boxes[no].gno = cg; } boxes[no].x1 = wx1; boxes[no].x2 = wx2; boxes[no].y1 = wy1; boxes[no].y2 = wy2; set_write_mode(1); draw_box(-2, no); break; case LINE: set_write_mode(0); draw_line(-2, no); if (lines[no].loctype == VIEW) { wx1 = xconv(wx1); wy1 = yconv(wy1); wx2 = xconv(wx2); wy2 = yconv(wy2); } else { lines[no].gno = cg; } lines[no].x1 = wx1; lines[no].x2 = wx2; lines[no].y1 = wy1; lines[no].y2 = wy2; set_write_mode(1); draw_line(-2, no); break; case STRING: set_write_mode(0); draw_string(-2, no); if (pstr[no].loctype == VIEW) { wx1 = xconv(wx1); wy1 = yconv(wy1); } else { pstr[no].gno = cg; } pstr[no].x = wx1; pstr[no].y = wy1; set_write_mode(1); draw_string(-2, no); break; } set_action(MOVE_OBJECT_1ST); break; /* * select a box or a line to move */ case EDIT_OBJECT: set_action(EDIT_OBJECT); device2world(x, y, &wx, &wy); find_item(cg, wx, wy, &ty, &no); if (ty < 0) { set_action(0); } else { switch (ty) { case BOX: break; case LINE: break; case STRING: break; } } break; /* * make a new box, select first corner */ case MAKE_BOX_1ST: set_action(MAKE_BOX_2ND); rectflag = 1; sx = x; sy = y; select_region(sx, sy, x, y); break; /* * make a new box, select opposite corner */ case MAKE_BOX_2ND: set_action(0); if ((boxno = next_box()) >= 0) { device2world(sx, sy, &wx1, &wy1); device2world(x, y, &wx2, &wy2); if (box_loctype == VIEW) { wx1 = xconv(wx1); wy1 = yconv(wy1); wx2 = xconv(wx2); wy2 = yconv(wy2); } else { boxes[no].gno = cg; } boxes[boxno].loctype = box_loctype; boxes[boxno].x1 = wx1; boxes[boxno].x2 = wx2; boxes[boxno].y1 = wy1; boxes[boxno].y2 = wy2; boxes[boxno].color = box_color; boxes[boxno].linew = box_linew; boxes[boxno].lines = box_lines; boxes[boxno].fill = box_fill; boxes[boxno].fillcolor = box_fillcolor; boxes[boxno].fillpattern = box_fillpat; draw_box(-2, boxno); } break; /* * locate angled string */ case STR_LOC1ST: set_action(STR_LOC2ND); rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); break; case STR_LOC2ND: device2world(sx, sy, &wx1, &wy1); device2world(x, y, &wx2, &wy2); wx1 = xconv(wx1); wy1 = yconv(wy1); wx2 = xconv(wx2); wy2 = yconv(wy2); string_rot = (int) ((atan2((wy2 - wy1) * win_h, (wx2 - wx1) * win_w) * 180.0 / M_PI) + 360.0) % 360; updatestrings(); strings_loc_proc(); break; /* * make a new line, select start point */ case MAKE_LINE_1ST: sx = x; sy = y; set_action(MAKE_LINE_2ND); rubber_flag = 1; select_line(sx, sy, x, y); break; /* * make a new line, select end point */ case MAKE_LINE_2ND: set_action(0); if ((lineno = next_line()) >= 0) { device2world(sx, sy, &wx1, &wy1); device2world(x, y, &wx2, &wy2); if (line_loctype == VIEW) { wx1 = xconv(wx1); wy1 = yconv(wy1); wx2 = xconv(wx2); wy2 = yconv(wy2); } else { lines[no].gno = cg; } lines[lineno].loctype = line_loctype; lines[lineno].x1 = wx1; lines[lineno].x2 = wx2; lines[lineno].y1 = wy1; lines[lineno].y2 = wy2; lines[lineno].color = line_color; lines[lineno].lines = line_lines; lines[lineno].linew = line_linew; lines[lineno].arrow = line_arrow; lines[lineno].asize = line_asize; lines[lineno].atype = line_atype; draw_line(-2, lineno); } break; /* * Edit an existing string */ case STR_EDIT: device2world(x, y, &wx, &wy); find_item(cg, wx, wy, &ty, &no); if ((ty >= 0) && (ty == STRING)) { int ilenx, ileny; wx1 = pstr[no].x; wy1 = pstr[no].y; if (pstr[no].loctype == VIEW) { /* in viewport coords */ view2world(wx1, wy1, &wx2, &wy2); wx1 = wx2; wy1 = wy2; } world2device(wx1, wy1, &strx, &stry); drawx = strx; drawy = stry; strcpy(tmpstr, pstr[no].s); setcharsize(pstr[no].charsize); setfont(pstr[no].font); setcolor(pstr[no].color); string_just = pstr[no].just; justflag = string_just; string_size = pstr[no].charsize; string_font = pstr[no].font; string_color = pstr[no].color; string_linew = pstr[no].linew; string_rot = pstr[no].rot; string_loctype = pstr[no].loctype; updatestrings(); kill_string(no); si = sin(M_PI / 180.0 * string_rot) * ((double) win_w) / ((double) win_h); co = cos(M_PI / 180.0 * string_rot); ilenx = stringextentx(charsize * xlibcharsize, tmpstr); ileny = stringextenty(charsize * xlibcharsize, tmpstr); switch (justflag) { case 1: strx = drawx + co * ilenx - si * ileny; stry = drawy + si * ilenx + co * ileny; break; case 2: strx = drawx + (co * ilenx - si * ileny) / 2; stry = drawy + (si * ilenx + co * ileny) / 2; break; } update_text_cursor(tmpstr, drawx, drawy); do_text_string(2, 0); action_flag = STR_LOC; } else { set_action(0); } break; /* * locate a string on the canvas */ case STR_LOC: if (tmpstr[0]) { device2world(strx, win_h - stry, &wx, &wy); define_string(tmpstr, wx, wy); } strx = x; stry = win_h - y; drawx = strx; drawy = stry; tmpstr[0] = 0; define_string_defaults(); justflag = string_just; setcharsize(string_size); xlibsetfont(string_font); xlibsetcolor(string_color); xlibsetlinewidth(string_linew); si = sin(M_PI / 180.0 * string_rot) * ((double) win_w) / ((double) win_h); co = cos(M_PI / 180.0 * string_rot); update_text_cursor(tmpstr, strx, stry); break; /* * Compute the area of a polygon */ case COMP_AREA: { double area, comp_area(); get_world(x, y, &polyx[npoly], &polyy[npoly]); ipolyx[npoly] = x; ipolyy[npoly] = y; npoly++; nipoly++; if (npoly <= 2) { area = 0.0; } else { area = comp_area(npoly, polyx, polyy); } sprintf(buf, "Area [%lf]", fabs(area)); panel_setmsgstr_value(locate_grid_item, buf); rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(COMP_AREA); } break; case COMP_PERIMETER: { double area, comp_perimeter(); get_world(x, y, &polyx[npoly], &polyy[npoly]); ipolyx[npoly] = x; ipolyy[npoly] = y; npoly++; nipoly++; if (npoly <= 1) { area = 0.0; } else { area = comp_perimeter(npoly, polyx, polyy); } sprintf(buf, "Perimeter [%lf]", fabs(area)); panel_setmsgstr_value(locate_grid_item, buf); rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(COMP_PERIMETER); } break; /* * place an isoline label */ case PLACE_ISOLINE_LABEL: { get_world(x, y, &wx, &wy); find_element(string_grid, wx, wy, &tmpind); if (tmpind >= 0) { define_depth_label(string_grid, tmpind, wx, wy); } else { errwin("No element found\n"); } set_action(PLACE_ISOLINE_LABEL); } break; /* * Pick prop */ case PICK_PROP_NODE: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &tmpind); if (tmpind >= 0) { diamond(grid[curgrid].xord[tmpind], grid[curgrid].yord[tmpind]); flush_pending(); prop_set(0, tmpind); } set_action(PICK_PROP_NODE); break; case PICK_PROP_ELEM: get_world(x, y, &wx, &wy); find_nearest_element(curgrid, wx, wy, &tmpind); if (tmpind >= 0) { get_center(curgrid, tmpind, &wx, &wy); writestr(wx, wy, 0, 0, "s"); flush_pending(); prop_set(0, tmpind); } set_action(PICK_PROP_ELEM); break; case QUERY_PROP_ELEM: get_world(x, y, &wx, &wy); find_nearest_element(curgrid, wx, wy, &tmpind); if (tmpind >= 0) { double d, prop_get(int, int); d = prop_get(0, tmpind); sprintf(buf, "Element %d: Prop = %.4lf", tmpind + 1, d); panel_setmsgstr_value(locate_grid_item, buf); } set_action(QUERY_PROP_ELEM); break; case PICK_ISTOK: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &tmpind); if (tmpind >= 0) { get_center(curgrid, tmpind, &wx, &wy); writestr(wx, wy, 0, 0, "w"); } set_action(PICK_ISTOK); break; case PICK_NODE_LIST: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &tmpind); if (tmpind >= 0) { AddToPNodeList(curnl, tmpind, curnlival, curnldval, curnlcolor); DrawPNodeLists(curgrid); } set_action(PICK_NODE_LIST); break; /* * select a reference point for the locator in main_panel */ case SEL_POINT: get_world(x, y, &wx, &wy); dsx = wx; dsy = wy; my_circle(dsx, dsy); set_action(0); break; /* * Center the world */ case CENTER_WORLD: get_world(x, y, &wx1, &wy1); write_mode_str("Click on the center of the new view"); dx = (xg1 + xg2) * 0.5 - wx1; dy = (yg1 + yg2) * 0.5 - wy1; xg1 = xg1 - dx; xg2 = xg2 - dx; yg1 = yg1 - dy; yg2 = yg2 - dy; set_up_world(); do_drawgrid(); set_action(CENTER_WORLD); break; /* * Move the world */ case MOVE_WORLD1ST: get_world(x, y, &wx1, &wy1); ox = x; oy = y; set_action(MOVE_WORLD2ND); write_mode_str("Move to the new view"); world2deviceabs(xg1, yg1, &sx, &sy); world2deviceabs(xg2, yg2, &xs, &ys); select_region(sx, sy, xs, ys); break; case MOVE_WORLD2ND: set_action(0); get_world(x, y, &wx2, &wy2); dx = wx2 - wx1; dy = wy2 - wy1; xg1 = xg1 - dx; xg2 = xg2 - dx; yg1 = yg1 - dy; yg2 = yg2 - dy; set_up_world(); do_drawgrid(); break; /* * set one corner of zoom */ case ZOOM_1ST: set_action(ZOOM_2ND); write_mode_str("Click on the opposite corner of rectangle to enlarge"); rectflag = 1; sx = x; sy = y; select_region(x, y, x, y); break; /* * set opposing corner of zoom */ case ZOOM_2ND: set_action(0); select_region(sx, sy, old_x, old_y); get_world(sx, sy, &wx1, &wy1); get_world(old_x, old_y, &wx2, &wy2); if (wx1 > wx2) fswap(&wx1, &wx2); if (wy1 > wy2) fswap(&wy1, &wy2); xg1 = wx1; xg2 = wx2; yg1 = wy1; yg2 = wy2; set_up_world(); do_drawgrid(); break; /* * set one corner of viewport */ case VIEW_1ST: set_action(VIEW_2ND); rectflag = 1; sx = x; sy = y; select_region(x, y, x, y); break; /* * set opposing corner of viewport */ case VIEW_2ND: { double vx1, vx2, vy1, vy2; extern double xv1, xv2, yv1, yv2; set_action(0); select_region(sx, sy, old_x, old_y); if (sx == old_x || sy == old_y) { errwin("Viewport size incorrect, not changed"); } else { device2world(sx, sy, &wx1, &wy1); device2world(old_x, old_y, &wx2, &wy2); world2view(wx1, wy1, &vx1, &vy1); world2view(wx2, wy2, &vx2, &vy2); if (vx1 > vx2) { fswap(&vx1, &vx2); } if (vy1 > vy2) { fswap(&vy1, &vy2); } xv1 = vx1; yv1 = vy1; xv2 = vx2; yv2 = vy2; set_up_world(); update_view(); do_drawgrid(); } } break; /* * The following are specific for gredit */ /* * Define an exterior boundary */ case EXTRACT_GRID: get_world(x, y, &polyx[npoly], &polyy[npoly]); ipolyx[npoly] = x; ipolyy[npoly] = y; npoly++; nipoly++; rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(EXTRACT_GRID); break; case DEF_EXT_BOUND: get_world(x, y, &polyx[npoly], &polyy[npoly]); ipolyx[npoly] = x; ipolyy[npoly] = y; npoly++; nipoly++; rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(DEF_EXT_BOUND); break; /* * Define an interior boundary */ case DEF_INT_BOUND: get_world(x, y, &polyx[npoly], &polyy[npoly]); ipolyx[npoly] = x; ipolyy[npoly] = y; npoly++; nipoly++; rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(DEF_INT_BOUND); break; /* * Move an exterior boundary point */ case MOVE_EXT_BOUND1ST: get_world(x, y, &wx, &wy); find_external_boundary_point(curgrid, wx, wy, &bnof, &indf); if (indf < 0) { set_action(0); return; } rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(MOVE_EXT_BOUND2ND); break; case MOVE_EXT_BOUND2ND: set_action(0); setcolor(0); diamond(wx, wy); setcolor(1); get_world(x, y, &wx, &wy); move_boundary_node(curgrid, bnof, indf, wx, wy); diamond(wx, wy); set_action(MOVE_EXT_BOUND1ST); break; /* * Move an interior boundary point */ case MOVE_INT_BOUND1ST: get_world(x, y, &wx, &wy); find_internal_boundary_point(curgrid, wx, wy, &bnof, &indf); if (indf < 0) { set_action(0); return; } rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(MOVE_INT_BOUND2ND); break; case MOVE_INT_BOUND2ND: set_action(0); setcolor(0); diamond(wx, wy); setcolor(1); get_world(x, y, &wx, &wy); move_boundary_node(curgrid, bnof, indf, wx, wy); diamond(wx, wy); set_action(MOVE_INT_BOUND1ST); break; /* * Delete an exterior boundary point */ case DEL_EXT_BOUNDPT: get_world(x, y, &wx, &wy); break; /* * Delete an interior boundary point */ case DEL_INT_BOUNDPT: get_world(x, y, &wx, &wy); break; /* * Delete an interior boundary */ case DEL_INT_BOUND: get_world(x, y, &wx, &wy); find_internal_boundary_point(curgrid, wx, wy, &ind1, &ind2); if (ind1 >= 0) { if (ind2 >= 0) { disassociate_grid(curgrid, ind1); } } break; /* * Add a point to a boundary */ case ADD_BOUND1: /* select 1st boundary node */ get_world(x, y, &wx, &wy); find_boundary_point(curgrid, wx, wy, &bnd1, &ind1); if (bnd1 < 0 || ind1 < 0) { set_action(0); } else { my_circlefilled(wx, wy); flush_pending(); set_action(ADD_BOUND2); } break; case ADD_BOUND2: /* select 2nd boundary node */ get_world(x, y, &wx, &wy); find_boundary_point(curgrid, wx, wy, &bnd2, &ind2); if (bnd1 != bnd2 || bnd2 < 0 || ind2 < 0) { set_action(0); } else { my_circlefilled(wx, wy); flush_pending(); set_action(ADD_BOUND3); } break; case ADD_BOUND3: /* select point to insert */ get_world(x, y, &wx, &wy); my_circlefilled(wx, wy); flush_pending(); add_boundary_node(curgrid, bnd1, ind1, ind2, wx, wy); set_action(ADD_BOUND1); break; /* * Spread points */ case ADD_BUILD1: get_world(x, y, &wx1, &wy1); switch (spreadflag) { case 0: rectflag = 1; sx = x; sy = y; select_region(x, y, x, y); break; case 1: rectflag = 1; sx = x; sy = y; select_region(x, y, x, y); break; case 2: rectflag = 1; sx = x; sy = y; select_region(x, y, x, y); break; case 3: rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); break; case 4: rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); break; } set_action(ADD_BUILD2); break; case ADD_BUILD2: set_action(0); switch (spreadflag) { case 0: select_region(sx, sy, old_x, old_y); get_world(sx, sy, &wx1, &wy1); get_world(old_x, old_y, &wx2, &wy2); if (wx1 > wx2) fswap(&wx1, &wx2); if (wy1 > wy2) fswap(&wy1, &wy2); spread_rectangular(curbuild, wx1, wy1, wx2, wy2); break; case 1: select_region(sx, sy, old_x, old_y); get_world(sx, sy, &wx1, &wy1); get_world(old_x, old_y, &wx2, &wy2); if (wx1 > wx2) fswap(&wx1, &wx2); if (wy1 > wy2) fswap(&wy1, &wy2); spread_rectangular_offset(curbuild, wx1, wy1, wx2, wy2); break; case 2: select_region(sx, sy, old_x, old_y); get_world(sx, sy, &wx1, &wy1); get_world(old_x, old_y, &wx2, &wy2); if (wx1 > wx2) fswap(&wx1, &wx2); if (wy1 > wy2) fswap(&wy1, &wy2); spread_random(curbuild, wx1, wy1, wx2, wy2); break; case 3: get_world(sx, sy, &wx1, &wy1); get_world(old_x, old_y, &wx2, &wy2); setlinewidth(3); my_move2(wx1, wy1); my_draw2(wx2, wy2); setlinewidth(1); set_action(ADD_BUILD3); break; case 4: get_world(sx, sy, &wx1, &wy1); get_world(old_x, old_y, &wx2, &wy2); setlinewidth(3); my_move2(wx1, wy1); my_draw2(wx2, wy2); setlinewidth(1); set_action(ADD_BUILD3); break; } break; case ADD_BUILD3: get_world(x, y, &wx3, &wy3); switch (spreadflag) { case 3: spread_rotated_rect(curbuild, wx1, wy1, wx2, wy2, wx3, wy3); break; case 4: spread_rotated_rect_offset(curbuild, wx1, wy1, wx2, wy2, wx3, wy3); break; } set_action(0); break; case GENFD_1ST: sx = x; sy = y; rubber_flag = 1; select_line(x, y, x, y); set_action(GENFD_2ND); break; case GENFD_2ND: set_action(0); get_world(sx, sy, &wx1, &wy1); get_world(old_x, old_y, &wx2, &wy2); setlinewidth(3); my_move2(wx1, wy1); my_draw2(wx2, wy2); setlinewidth(1); set_action(GENFD_3RD); sx = old_x; sy = old_y; rubber_flag = 1; select_line(old_x, old_y, old_x, old_y); break; case GENFD_3RD: get_world(old_x, old_y, &wx3, &wy3); set_action(0); setlinewidth(3); my_move2(wx2, wy2); my_draw2(wx3, wy3); setlinewidth(1); genfd_grid(wx1, wy1, wx2, wy2, wx3, wy3); break; /* * Add a nodal point (in the current grid) to a boundary */ case ADD_NODE_BOUND1: /* select 1st boundary node */ get_world(x, y, &wx, &wy); break; case ADD_NODE_BOUND2: /* select 2nd boundary node */ get_world(x, y, &wx, &wy); break; case ADD_NODE_BOUND3: /* select nodal point */ get_world(x, y, &wx, &wy); break; /* * Place a single build point */ case PLACE_BUILD: get_world(x, y, &wx1, &wy1); if (goodpoint(curgrid, wx1, wy1)) { add_build(curbuild, wx1, wy1, 1.0); setcolor(2); box(wx1, wy1); flush_pending(); setcolor(1); } set_action(PLACE_BUILD); break; /* * Delete a single build point */ case DELETE_BUILD: get_world(x, y, &wx, &wy); accumulate_nearest_buildpts(curbuild, wx, wy); set_action(DELETE_BUILD); break; /* * Move a single build point */ case MOVE_BUILD1ST: get_world(x, y, &wx, &wy); find_nearest_buildpt(curbuild, wx, wy, &indf); if (indf < 0) { set_action(0); return; } wx = build[curbuild].bx[indf]; wy = build[curbuild].by[indf]; get_device(wx, wy, &x, &y); rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(MOVE_BUILD2ND); break; case MOVE_BUILD2ND: setcolor(0); box(wx, wy); setcolor(1); get_world(x, y, &wx, &wy); move_buildpt(curbuild, indf, wx, wy); set_action(0); box(wx, wy); flush_pending(); set_action(MOVE_BUILD1ST); break; /* * Place a build point arc */ case PLACE_BUILD_ARC: get_world(x, y, &wx, &wy); break; /* * Report on the nearest node to the mouse location */ case GET_NEAREST_NODE: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &ind1); wx = grid[curgrid].xord[ind1]; wy = grid[curgrid].yord[ind1]; if (ind1 >= 0) { sprintf(buf, "Node %d: [%.2lf,%.2lf], depth = %.3lf", ind1 + 1, wx, wy, grid[curgrid].depth[ind1]); } panel_setmsgstr_value(locate_grid_item, buf); set_action(GET_NEAREST_NODE); break; case GET_NEAREST_BUILDPT: get_world(x, y, &wx, &wy); find_nearest_buildpt(0, wx, wy, &ind1); if (ind1 >= 0) { wx = build[0].bx[ind1]; wy = build[0].by[ind1]; sprintf(buf, "Point %d: [%.2lf,%.2lf], depth = %.3lf", ind1 + 1, wx, wy, build[0].db[ind1]); panel_setmsgstr_value(locate_grid_item, buf); } set_action(GET_NEAREST_BUILDPT); break; case GET_DEPTH_ALL: { double backd = 0.0, editd = 0.0, buildd = 0.0; int backi, editi, buildi; char tbuf[256]; get_world(x, y, &wx, &wy); find_nearest_buildpt(0, wx, wy, &buildi); if (buildi >= 0) { wx = build[0].bx[buildi]; wy = build[0].by[buildi]; buildd = build[0].db[buildi]; } find_element(curgrid, wx, wy, &editi); if (editi >= 0) { editd = get_depth_element(curgrid, editi, wx, wy); } find_element(backgrid, wx, wy, &backi); if (backi >= 0) { backd = get_depth_element(backgrid, backi, wx, wy); } sprintf(buf, "Point %d, Edit el %d, Back el %d: [%.2lf,%.2lf], %.3lf, %.3lf, %.3lf", buildi + 1, editi + 1, backi + 1, wx, wy, buildd, editd, backd); panel_setmsgstr_value(locate_grid_item, buf); set_action(GET_DEPTH_ALL); } break; /* * Report on the nearest element to the mouse location */ case GET_NEAREST_ELEMENT: get_world(x, y, &wx, &wy); find_nearest_element(curgrid, wx, wy, &ind1); if (ind1 >= 0) { double quadqual(int gno, int e); switch (grid[curgrid].icon[ind1].type) { case 3: case 6: n0 = grid[curgrid].icon[ind1].nl[0] + 1; n1 = grid[curgrid].icon[ind1].nl[1] + 1; n2 = grid[curgrid].icon[ind1].nl[2] + 1; wx = area(curgrid, ind1); if (wx < 0.0) { wy = sqrt(-wx / M_PI); } else { wy = sqrt(wx / M_PI); } sprintf(buf, "Element %d: [%d %d %d], A = %.2lf, ER = %.2lf", ind1 + 1, n0, n1, n2, wx, wy); break; case 4: case 8: n0 = grid[curgrid].icon[ind1].nl[0] + 1; n1 = grid[curgrid].icon[ind1].nl[1] + 1; n2 = grid[curgrid].icon[ind1].nl[2] + 1; n3 = grid[curgrid].icon[ind1].nl[3] + 1; sprintf(buf, "Element %d: [%d %d %d %d] Q = %.3lf", ind1 + 1, n0, n1, n2, n3, quadqual(curgrid, ind1)); break; } } else { sprintf(buf, "No element found"); } get_center(curgrid, ind1, &wx, &wy); my_circlefilled(wx, wy); panel_setmsgstr_value(locate_grid_item, buf); set_action(GET_NEAREST_ELEMENT); break; /* * Report on the element containing the current mouse location */ case GET_ELEMENT: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &ind1); if (ind1 >= 0) { double quadqual(int gno, int e); switch (grid[curgrid].icon[ind1].type) { case 3: case 6: n0 = grid[curgrid].icon[ind1].nl[0] + 1; n1 = grid[curgrid].icon[ind1].nl[1] + 1; n2 = grid[curgrid].icon[ind1].nl[2] + 1; wx = area(curgrid, ind1); if (wx < 0.0) { wy = sqrt(-wx / M_PI); } else { wy = sqrt(wx / M_PI); } sprintf(buf, "Element %d: [%d %d %d], A = %.2lf, ER = %.2lf", ind1 + 1, n0, n1, n2, wx, wy); break; case 4: case 8: n0 = grid[curgrid].icon[ind1].nl[0] + 1; n1 = grid[curgrid].icon[ind1].nl[1] + 1; n2 = grid[curgrid].icon[ind1].nl[2] + 1; n3 = grid[curgrid].icon[ind1].nl[3] + 1; sprintf(buf, "Element %d: [%d %d %d %d] Q = %.3lf", ind1 + 1, n0, n1, n2, n3, quadqual(curgrid, ind1)); break; } } else { sprintf(buf, "No element found"); } panel_setmsgstr_value(locate_grid_item, buf); set_action(GET_ELEMENT); break; /* * Verbose report on the node and element */ case GET_ALL: get_world(x, y, &wx, &wy); break; /* * Get the depth at the mouse location */ case GET_GRID_DEPTH: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &ind1); if (ind1 >= 0) { sprintf(buf, "Element %d: at (%lf, %lf) Depth = %lf", ind1 + 1, wx, wy, get_depth_element(curgrid, ind1, wx, wy)); panel_setmsgstr_value(locate_grid_item, buf); set_action(GET_GRID_DEPTH); } break; case GET_BACK_DEPTH: get_world(x, y, &wx, &wy); find_element(backgrid, wx, wy, &ind1); if (ind1 >= 0) { sprintf(buf, "Element %d: at (%lf, %lf) Depth = %lf", ind1 + 1, wx, wy, get_depth_element(backgrid, ind1, wx, wy)); panel_setmsgstr_value(locate_grid_item, buf); set_action(GET_BACK_DEPTH); } get_world(x, y, &wx, &wy); break; /* * Move the node nearest the mouse location */ case MOVE_NODE1ST: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &tmpind); wx = grid[curgrid].xord[tmpind]; wy = grid[curgrid].yord[tmpind]; get_device(wx, wy, &sx, &sy); rubber_flag = 1; select_line(sx, sy, sx, sy); set_action(MOVE_NODE2ND); break; case MOVE_NODE2ND: set_action(0); get_world(x, y, &wx, &wy); setcolor(0); find_assoc_elements(curgrid, tmpind, &nibuf, ibuf); draw_elements(curgrid, nibuf, ibuf, redfact); setcolor(1); grid[curgrid].xord[tmpind] = wx; grid[curgrid].yord[tmpind] = wy; draw_elements(curgrid, nibuf, ibuf, redfact); flush_pending(); set_action(MOVE_NODE1ST); break; /* * Delete the elements containing the mouse pointer */ case DELETE_ELEMENTS: get_world(x, y, &wx, &wy); accumulate_elements(curgrid, wx, wy); find_element(curgrid, wx, wy, &ind1); if (ind1 >= 0) { get_center(curgrid, ind1, &wx, &wy); solidbox(wx, wy); flush_pending(); } set_action(DELETE_ELEMENTS); break; /* * Delete the element with center of mass nearest mouse pointer */ case DELETE_ELEMENT: get_world(x, y, &wx, &wy); accumulate_nearest_elements(curgrid, wx, wy); set_action(DELETE_ELEMENT); break; /* * Add a node to the table of nodes */ case ADD_NODE: get_world(x, y, &wx, &wy); my_circlefilled(wx, wy); my_move2(wx, wy); add_node(curgrid, wx, wy, 1.0); set_action(ADD_NODE); break; /* * Delete the nearest node and all associated elements */ case DELETE_NODE: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &ind1); if (ind1 >= 0) { writestr(wx, wy, 0, 0, "x"); delete_node(curgrid, ind1); set_action(DELETE_NODE); } else { errwin("No node found!"); set_action(0); } break; /* * Add an element to the table of elements */ case ADD_ELEMENT1: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &ind1); writestr(wx, wy, 0, 0, "1"); set_action(ADD_ELEMENT2); break; case ADD_ELEMENT2: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &ind2); writestr(wx, wy, 0, 0, "2"); set_action(ADD_ELEMENT3); break; case ADD_ELEMENT3: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &ind3); if (area_from_nodes(curgrid, ind1, ind2, ind3) <= 0.0) { iswap(&ind1, &ind3); writestr(wx, wy, 0, 0, "3 (swapped, area <= 0.0)"); } else { writestr(wx, wy, 0, 0, "3"); } tmpind = grid[curgrid].nmel; add_element(curgrid, ind1, ind2, ind3); draw_element(curgrid, tmpind, redfact); my_move2(wx, wy); set_action(ADD_ELEMENT1); break; /* * Add a quadratic element to the table of elements */ case ADD_QUAD1: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &ind1); writestr(wx, wy, 0, 0, "1"); set_action(ADD_QUAD2); break; case ADD_QUAD2: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &ind2); writestr(wx, wy, 0, 0, "2"); set_action(ADD_QUAD3); break; case ADD_QUAD3: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &ind3); writestr(wx, wy, 0, 0, "3"); set_action(ADD_QUAD4); break; case ADD_QUAD4: get_world(x, y, &wx, &wy); find_nearest_node(curgrid, wx, wy, &ind4); /* if (area_from_nodes(curgrid, ind1, ind2, ind3) <= 0.0) { iswap(&ind1, &ind3); writestr(wx, wy, 0, 0, "3 (swapped, area <= 0.0)"); } else { writestr(wx, wy, 0, 0, "3"); } */ writestr(wx, wy, 0, 0, "4"); tmpind = grid[curgrid].nmel; add_element2(curgrid, 4, ind1, ind2, ind3, ind4); draw_element(curgrid, tmpind, redfact); my_move2(wx, wy); set_action(ADD_QUAD1); break; case CONV_4TO3: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &ind1); if (ind1 >= 0) { get_center(curgrid, ind1, &wx, &wy); writestr(wx, wy, 0, 0, "q"); flush_pending(); quad_to_tris(curgrid, ind1); set_action(CONV_4TO3); } else { set_action(0); } break; case CONV_3TO4_1ST: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &ind1); if (ind1 >= 0) { get_center(curgrid, ind1, &wx, &wy); writestr(wx, wy, 0, 0, "1"); flush_pending(); set_action(CONV_3TO4_2ND); } else { set_action(0); } break; case CONV_3TO4_2ND: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &ind2); if (ind2 >= 0) { get_center(curgrid, ind2, &wx, &wy); writestr(wx, wy, 0, 0, "2"); flush_pending(); tris_to_quad(curgrid, ind1, ind2); set_action(CONV_3TO4_1ST); } else { set_action(0); } break; case EDIT_NODE: break; case CONV_NODE2COL: break; /* * Swap the line between two elements */ case SWAPLINE_1ST: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &ind1); set_action(0); if (ind1 >= 0) { get_center(curgrid, ind1, &wx, &wy); writestr(wx, wy, 0, 0, "1"); set_action(SWAPLINE_2ND); } break; case SWAPLINE_2ND: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &ind2); set_action(0); if (ind2 >= 0) { get_center(curgrid, ind2, &wx, &wy); writestr(wx, wy, 0, 0, "2"); setcolor(0); draw_element(curgrid, ind1, redfact); draw_element(curgrid, ind2, redfact); setcolor(1); swapline(curgrid, ind1, ind2); draw_element(curgrid, ind1, redfact); draw_element(curgrid, ind2, redfact); my_move2(wx, wy); } set_action(SWAPLINE_1ST); break; /* * Snap nodes to a line */ case SELECT_SNAP: get_world(x, y, &wx, &wy); accumulate_nearest_nodes(curgrid, wx, wy); set_action(SELECT_SNAP); break; case SNAP_LINE1ST: get_world(x, y, &wx1, &wy1); set_action(0); set_action(SNAP_LINE2ND); rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); break; case SNAP_LINE2ND: get_world(x, y, &wx2, &wy2); if (wx2 - wx1 == 0.0) { sm = 1.0e37; sb = wx1; } else { sm = (wy2 - wy1) / (wx2 - wx1); sb = wy2 - sm * wx2; } nibuf = 0; set_action(0); write_mode_str("Select nodes to snap with left button, middle button to register, right button to abort"); set_action(SELECT_SNAP); select_line(sx, sy, x, y); break; /* * Split an element into 3 elements */ case SPLIT_ELEMENT3: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &tmpind); if (tmpind >= 0) { /* get_center(curgrid, tmpind, &wx, &wy); writestr(wx, wy, 0, 0, "3"); */ split_elem3(curgrid, tmpind); } break; case SPLIT_ELEMENTS3: break; /* * Split an element into 4 elements */ case SPLIT_ELEMENT4: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &tmpind); if (tmpind >= 0) { /* get_center(curgrid, tmpind, &wx, &wy); writestr(wx, wy, 0, 0, "4"); */ split_elem4(curgrid, tmpind); } break; case SPLIT_ELEMENTS4: break; /* * Cut a grid by a line */ case CUT_GRID1ST: rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(CUT_GRID2ND); break; case CUT_GRID2ND: set_action(0); get_world(sx, sy, &wx1, &wy1); get_world(x, y, &wx2, &wy2); cut_grid(curgrid, wx1, wy1, wx2, wy2, cutgrid_type); do_drawgrid(); break; /* * Define a region for operations */ case DEFINE_REGION: { get_world(x, y, ®ionx[nregion], ®iony[nregion]); ipolyx[npoly] = x; ipolyy[npoly] = y; nipoly++; nregion++; rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(DEFINE_REGION); } break; /* * Slice a grid */ case SLICE_BATH1ST: get_world(x, y, &wx1, &wy1); find_element(curgrid, wx1, wy1, &tmpind); if (tmpind >= 0) { rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(SLICE_BATH2ND); } else { set_action(0); } break; case SLICE_BATH2ND: get_world(x, y, &wx2, &wy2); find_element(curgrid, wx2, wy2, &tmpind); if (tmpind >= 0) { extern int slice_back; get_slice(curgrid, wx1, wy1, wx2, wy2, 1); if (slice_back) { get_slice(MAXGRIDS, wx1, wy1, wx2, wy2, 0); } } else { } set_action(0); break; case SLICE_GRIDBATH1ST: get_world(x, y, &wx1, &wy1); find_element(curgrid, wx1, wy1, &tmpind); if (tmpind >= 0) { rubber_flag = 1; sx = x; sy = y; select_line(sx, sy, x, y); set_action(SLICE_GRIDBATH2ND); } else { set_action(0); } break; case SLICE_GRIDBATH2ND: get_world(x, y, &wx2, &wy2); find_element(curgrid, wx2, wy2, &tmpind); if (tmpind >= 0) { set_action(0); my_move2(wx1, wy1); my_draw2(wx2, wy2); } else { set_action(0); } set_action(SLICE_GRIDBATH3RD); break; case SLICE_GRIDBATH3RD: get_world(x, y, &wx, &wy); find_element(curgrid, wx, wy, &tmpind); if (tmpind >= 0) { box(wx, wy); flush_pending(); slice_bygrid(curgrid, wx1, wy1, wx2, wy2, wx, wy); } else { } set_action(0); break; case OPENB1ST: { int bno = grid[curgrid].boundaries[0]; set_action(OPENB2ND); get_world(x, y, &wx1, &wy1); find_nearest_boundary_point2(bno, wx1, wy1, &ind1); if (ind1 >= 0) { diamond(boundary[bno].boundx[ind1], boundary[bno].boundy[ind1]); flush_pending(); } else { errwin("No boundary point found"); set_action(0); } } break; case OPENB2ND: { int bno = grid[curgrid].boundaries[0]; set_action(OPENB1ST); get_world(x, y, &wx2, &wy2); find_nearest_boundary_point2(bno, wx2, wy2, &ind2); diamond(boundary[bno].boundx[ind2], boundary[bno].boundy[ind2]); define_adcirc_openb(0, ind1, ind2); draw_adcirc_openb(0); flush_pending(); } break; case LANDB1ST: { int bno = grid[curgrid].boundaries[0]; set_action(LANDB2ND); get_world(x, y, &wx1, &wy1); find_nearest_boundary_point2(bno, wx1, wy1, &ind1); if (ind1 >= 0) { diamond(boundary[bno].boundx[ind1], boundary[bno].boundy[ind1]); flush_pending(); } else { errwin("No boundary point found"); set_action(0); } } break; case LANDB2ND: { int bno = grid[curgrid].boundaries[0]; set_action(LANDB1ST); get_world(x, y, &wx2, &wy2); find_nearest_boundary_point2(bno, wx2, wy2, &ind2); diamond(boundary[bno].boundx[ind2], boundary[bno].boundy[ind2]); define_adcirc_landb(0, ind1, ind2); draw_adcirc_landb(0); flush_pending(); } break; case PICK_BATH: { rubber_flag = 1; sx = x; sy = y; get_world(x, y, &wx, &wy); slicex[slice_npts] = wx; slicey[slice_npts] = wy; slice_npts++; set_action(PICK_BATH); } break; case PLACE_MAPSCALE: set_action(0); device2world(x, y, &wx, &wy); set_mapscale_loc(wx, wy); break; case PLACE_ISOLINES_LEGEND: device2world(x, y, &wx, &wy); set_isolleg_loc(wx, wy); set_action(0); break; case PLACE_VSCALE: { extern double grad_legx, grad_legy; get_world(x, y, &grad_legx, &grad_legy); set_action(0); } break; } break; case Button2: switch (action_flag) { case EXTRACT_GRID: get_world(x, y, &polyx[npoly], &polyy[npoly]); npoly++; if (npoly > 2) { extract_grid(polyx, polyy, npoly); } set_action(0); do_drawgrid(); break; case DEF_EXT_BOUND: { int ib, i; get_world(x, y, &polyx[npoly], &polyy[npoly]); npoly++; if (npoly > 2) { Free_boundary(grid[curgrid].boundaries[0]); if (grid[curgrid].nbounds > 0) { grid[curgrid].nbounds--; } ib = nextboundary(); grid[curgrid].boundaries[0] = ib; Allocate_boundary(ib, npoly, 0); grid[curgrid].nbounds++; for (i = 0; i < npoly; i++) { boundary[ib].boundx[i] = polyx[i]; boundary[ib].boundy[i] = polyy[i]; } ebound_defined = 1; update_fuzz_items(); } } set_action(0); do_drawgrid(); break; case DEF_INT_BOUND: { int ib, i; get_world(x, y, &polyx[npoly], &polyy[npoly]); npoly++; if (npoly > 2) { ib = nextboundary(); Allocate_boundary(ib, npoly, 1); for (i = 0; i < npoly; i++) { boundary[ib].boundx[i] = polyx[i]; boundary[ib].boundy[i] = polyy[i]; } associate_grid(curgrid, ib); ibound_defined = 1; update_fuzz_items(); } } set_action(0); do_drawgrid(); break; case DEFINE_REGION: if (nregion >= 3) { region_flag = 1; draw_region(regionx, regiony, nregion); } else { nregion = 0; region_flag = 0; } break; case PICK_BATH: { extern int slice_back; write_slice(curgrid, 1); if (slice_back) { write_slice(backgrid, 0); } } break; case DELETE_BUILD: delete_build_points(curbuild, ibuf, nibuf); do_drawgrid(); break; case DELETE_ELEMENT: case DELETE_ELEMENTS: delete_elements(curgrid, ibuf, nibuf); break; case SPLIT_ELEMENTS3: break; case SPLIT_ELEMENTS4: break; case SELECT_SNAP: { int i; double x, y, r, at, xinter; for (i = 0; i < nibuf; i++) { x = grid[curgrid].xord[ibuf[i]]; y = grid[curgrid].yord[ibuf[i]]; if (sm == 1e37) { grid[curgrid].xord[ibuf[i]] = sb; grid[curgrid].yord[ibuf[i]] = y; } else if (sm == 0.0) { grid[curgrid].xord[ibuf[i]] = x; grid[curgrid].yord[ibuf[i]] = sb; } else { r = y + 1.0 / sm * x; xinter = (r - sb) / (sm + 1.0 / sm); grid[curgrid].xord[ibuf[i]] = xinter; grid[curgrid].yord[ibuf[i]] = sm * xinter + sb; } } do_drawgrid(); set_action(0); } break; default: break; } npoly = 0; nipoly = 0; nibuf = 0; slice_npts = 0; set_action(0); break; } break; case MotionNotify: x = event->xmotion.x; y = event->xmotion.y; if (event->xmotion.state & Button1MotionMask) { switch (action_flag) { /* * Delete build points */ case DELETE_BUILD: get_world(x, y, &wx, &wy); accumulate_nearest_buildpts(curbuild, wx, wy); set_action(DELETE_BUILD); break; /* * Delete the element with center of mass nearest mouse pointer */ case DELETE_ELEMENT: get_world(x, y, &wx, &wy); accumulate_nearest_elements(curgrid, wx, wy); set_action(DELETE_ELEMENT); break; } } getpoints(x, y); break; default: break; } /* * some mouse tracking stuff */ switch (action_flag) { case MOVE_WORLD2ND: select_region(sx, sy, xs, ys); sx = sx - (ox - x); sy = sy - (oy - y); xs = xs - (ox - x); ys = ys - (oy - y); ox = x; oy = y; select_region(sx, sy, xs, ys); break; case MOVE_OBJECT_2ND: dx = sx - x; dy = sy - y; switch (ty) { case BOX: select_region(sx, sy, xs, ys); sx = x; sy = y; xs = xs - dx; ys = ys - dy; select_region(sx, sy, xs, ys); break; case LINE: select_line(sx, sy, xs, ys); sx = x; sy = y; xs = xs - dx; ys = ys - dy; select_line(sx, sy, xs, ys); break; case STRING: select_region(sx, sy, xs, ys); sx = x; sy = y; xs = xs - dx; ys = ys - dy; select_region(sx, sy, xs, ys); break; } break; case STR_LOC: break; } if (rectflag) { select_region(sx, sy, old_x, old_y); select_region(sx, sy, x, y); } if (rotrectflag) { select_rotated_rect(sx1, sy1, sx2, sy2, sx3, sy3); select_rotated_rect(sx1, sy1, sx2, sy2, sx3, sy3); } if (rubber_flag) { select_line(sx, sy, old_x, old_y); select_line(sx, sy, x, y); } old_x = x; old_y = y; }