/* getPath * Construct the shortest path from one endpoint of e to the other. * The obstacles and their number are given by obs and npoly. * vconfig is a precomputed data structure to help in the computation. * If chkPts is true, the function finds the polygons, if any, containing * the endpoints and tells the shortest path computation to ignore them. * Assumes this info is set in ND_lim, usually from _spline_edges. * Returns the shortest path. */ Ppolyline_t getPath(edge_t * e, vconfig_t * vconfig, int chkPts, Ppoly_t ** obs, int npoly) { Ppolyline_t line; int pp, qp; Ppoint_t p, q; p = add_pointf(ND_coord(agtail(e)), ED_tail_port(e).p); q = add_pointf(ND_coord(aghead(e)), ED_head_port(e).p); /* determine the polygons (if any) that contain the endpoints */ pp = qp = POLYID_NONE; if (chkPts) { pp = ND_lim(agtail(e)); qp = ND_lim(aghead(e)); /* for (i = 0; i < npoly; i++) { if ((pp == POLYID_NONE) && in_poly(*obs[i], p)) pp = i; if ((qp == POLYID_NONE) && in_poly(*obs[i], q)) qp = i; } */ } Pobspath(vconfig, p, pp, q, qp, &line); return line; }
/* process vgpane methods */ static int vgpanecmd(ClientData clientData, Tcl_Interp * interp, int argc, char *argv[]) { int vargc, length, i, j, n, result; char c, *s, **vargv, vbuf[30]; vgpane_t *vgp, **vgpp; point p, q, *ps; poly *tpp; double alpha, gain; Pvector_t slopes[2]; Ppolyline_t line, spline; int pp, qp; /* polygon indices for p, q */ Pedge_t *barriers; int n_barriers; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", " ", argv[0], " method ?arg arg ...?\"", (char *) NULL); return TCL_ERROR; } if (!(vgpp = (vgpane_t **) tclhandleXlate(vgpaneTable, argv[0]))) { Tcl_AppendResult(interp, "Invalid handle: \"", argv[0], "\"", (char *) NULL); return TCL_ERROR; } vgp = *vgpp; c = argv[1][0]; length = strlen(argv[1]); if ((c == 'c') && (strncmp(argv[1], "coords", length) == 0)) { if ((argc < 3)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " id ?x1 y1 x2 y2...?\"", (char *) NULL); return TCL_ERROR; } if (sscanf(argv[2], "%d", &polyid) != 1) { Tcl_AppendResult(interp, "not an integer: ", argv[2], (char *) NULL); return TCL_ERROR; } if (argc == 3) { /* find poly and return its coordinates */ for (i = 0; i < vgp->Npoly; i++) { if (vgp->poly[i].id == polyid) { n = vgp->poly[i].boundary.pn; for (j = 0; j < n; j++) { appendpoint(interp, vgp->poly[i].boundary.ps[j]); } return TCL_OK; } } Tcl_AppendResult(interp, " no such polygon: ", argv[2], (char *) NULL); return TCL_ERROR; } /* accept either inline or delimited list */ if ((argc == 4)) { result = Tcl_SplitList(interp, argv[3], &vargc, (CONST84 char ***) &vargv); if (result != TCL_OK) { return result; } } else { vargc = argc - 3; vargv = &argv[3]; } if (!vargc || vargc % 2) { Tcl_AppendResult(interp, "There must be a multiple of two terms in the list.", (char *) NULL); return TCL_ERROR; } /* remove old poly, add modified polygon to the end with the same id as the original */ if (!(remove_poly(vgp, polyid))) { Tcl_AppendResult(interp, " no such polygon: ", argv[2], (char *) NULL); return TCL_ERROR; } return (insert_poly(interp, vgp, polyid, vargv, vargc)); } else if ((c == 'd') && (strncmp(argv[1], "debug", length) == 0)) { /* debug only */ printf("debug output goes here\n"); return TCL_OK; } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) { /* delete a vgpane and all memory associated with it */ if (vgp->vc) Pobsclose(vgp->vc); free(vgp->poly); /* ### */ Tcl_DeleteCommand(interp, argv[0]); free((char *) tclhandleFree(vgpaneTable, argv[0])); return TCL_OK; } else if ((c == 'f') && (strncmp(argv[1], "find", length) == 0)) { /* find the polygon that the point is inside and return it id, or null */ if ((argc < 3)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " x y\"", (char *) NULL); return TCL_ERROR; } if (argc == 3) { result = Tcl_SplitList(interp, argv[2], &vargc, (CONST84 char ***) &vargv); if (result != TCL_OK) { return result; } } else { vargc = argc - 2; vargv = &argv[2]; } result = scanpoint(interp, &vargv[0], &p); if (result != TCL_OK) return result; /* determine the polygons (if any) that contain the point */ for (i = 0; i < vgp->Npoly; i++) { if (in_poly(vgp->poly[i].boundary, p)) { sprintf(vbuf, "%d", vgp->poly[i].id); Tcl_AppendElement(interp, vbuf); } } return TCL_OK; } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)) { /* add poly to end poly list, and it coordinates to the end of the point list */ if ((argc < 3)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " x1 y1 x2 y2 ...\"", (char *) NULL); return TCL_ERROR; } /* accept either inline or delimited list */ if ((argc == 3)) { result = Tcl_SplitList(interp, argv[2], &vargc, (CONST84 char ***) &vargv); if (result != TCL_OK) { return result; } } else { vargc = argc - 2; vargv = &argv[2]; } if (!vargc || vargc % 2) { Tcl_AppendResult(interp, "There must be a multiple of two terms in the list.", (char *) NULL); return TCL_ERROR; } polyid++; result = insert_poly(interp, vgp, polyid, vargv, vargc); if (result != TCL_OK) return result; sprintf(vbuf, "%d", polyid); Tcl_AppendResult(interp, vbuf, (char *) NULL); return TCL_OK; } else if ((c == 'l') && (strncmp(argv[1], "list", length) == 0)) { /* return list of polygon ids */ for (i = 0; i < vgp->Npoly; i++) { sprintf(vbuf, "%d", vgp->poly[i].id); Tcl_AppendElement(interp, vbuf); } return TCL_OK; } else if ((c == 'p') && (strncmp(argv[1], "path", length) == 0)) { /* return a list of points corresponding to the shortest path that does not cross the remaining "visible" polygons. */ if ((argc < 3)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " x1 y1 x2 y2\"", (char *) NULL); return TCL_ERROR; } if (argc == 3) { result = Tcl_SplitList(interp, argv[2], &vargc, (CONST84 char ***) &vargv); if (result != TCL_OK) { return result; } } else { vargc = argc - 2; vargv = &argv[2]; } if ((vargc < 4)) { Tcl_AppendResult(interp, "invalid points: should be: \"x1 y1 x2 y2\"", (char *) NULL); return TCL_ERROR; } result = scanpoint(interp, &vargv[0], &p); if (result != TCL_OK) return result; result = scanpoint(interp, &vargv[2], &q); if (result != TCL_OK) return result; /* only recompute the visibility graph if we have to */ if ((vc_refresh(vgp))) { Pobspath(vgp->vc, p, POLYID_UNKNOWN, q, POLYID_UNKNOWN, &line); for (i = 0; i < line.pn; i++) { appendpoint(interp, line.ps[i]); } } return TCL_OK; } else if ((c == 'b') && (strncmp(argv[1], "bind", length) == 0)) { if ((argc < 2) || (argc > 4)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " bind triangle ?command?\"", (char *) NULL); return TCL_ERROR; } if (argc == 2) { Tcl_AppendElement(interp, "triangle"); return TCL_OK; } length = strlen(argv[2]); if (strncmp(argv[2], "triangle", length) == 0) { s = vgp->triangle_cmd; if (argc == 4) vgp->triangle_cmd = s = buildBindings(s, argv[3]); } else { Tcl_AppendResult(interp, "unknown event \"", argv[2], "\": must be one of:\n\ttriangle.", (char *) NULL); return TCL_ERROR; } if (argc == 3) Tcl_AppendResult(interp, s, (char *) NULL); return TCL_OK; } else if ((c == 'b') && (strncmp(argv[1], "bpath", length) == 0)) { /* return a list of points corresponding to the shortest path that does not cross the remaining "visible" polygons. */ if ((argc < 3)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " x1 y1 x2 y2\"", (char *) NULL); return TCL_ERROR; } if (argc == 3) { result = Tcl_SplitList(interp, argv[2], &vargc, (CONST84 char ***) &vargv); if (result != TCL_OK) { return result; } } else { vargc = argc - 2; vargv = &argv[2]; } if ((vargc < 4)) { Tcl_AppendResult(interp, "invalid points: should be: \"x1 y1 x2 y2\"", (char *) NULL); return TCL_ERROR; } result = scanpoint(interp, &vargv[0], &p); if (result != TCL_OK) return result; result = scanpoint(interp, &vargv[2], &q); if (result != TCL_OK) return result; /* determine the polygons (if any) that contain the endpoints */ pp = qp = POLYID_NONE; for (i = 0; i < vgp->Npoly; i++) { tpp = &(vgp->poly[i]); if ((pp == POLYID_NONE) && in_poly(tpp->boundary, p)) pp = i; if ((qp == POLYID_NONE) && in_poly(tpp->boundary, q)) qp = i; } if (vc_refresh(vgp)) { /*Pobspath(vgp->vc, p, pp, q, qp, &line); */ Pobspath(vgp->vc, p, POLYID_UNKNOWN, q, POLYID_UNKNOWN, &line); make_barriers(vgp, pp, qp, &barriers, &n_barriers); slopes[0].x = slopes[0].y = 0.0; slopes[1].x = slopes[1].y = 0.0; Proutespline(barriers, n_barriers, line, slopes, &spline); for (i = 0; i < spline.pn; i++) { appendpoint(interp, spline.ps[i]); } } return TCL_OK; } else if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) { if ((argc < 3)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " id\"", (char *) NULL); return TCL_ERROR; } if (sscanf(argv[2], "%d", &polyid) != 1) { Tcl_AppendResult(interp, "not an integer: ", argv[2], (char *) NULL); return TCL_ERROR; } for (i = 0; i < vgp->Npoly; i++) { if (vgp->poly[i].id == polyid) { Ppoly_t pp = vgp->poly[i].boundary; point LL, UR; LL = UR = pp.ps[0]; for (j = 1; j < pp.pn; j++) { p = pp.ps[j]; if (p.x > UR.x) UR.x = p.x; if (p.y > UR.y) UR.y = p.y; if (p.x < LL.x) LL.x = p.x; if (p.y < LL.y) LL.y = p.y; } appendpoint(interp, LL); appendpoint(interp, UR); return TCL_OK; } } Tcl_AppendResult(interp, " no such polygon: ", argv[2], (char *) NULL); return TCL_ERROR; } else if ((c == 'c') && (strncmp(argv[1], "center", length) == 0)) { if ((argc < 3)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " id\"", (char *) NULL); return TCL_ERROR; } if (sscanf(argv[2], "%d", &polyid) != 1) { Tcl_AppendResult(interp, "not an integer: ", argv[2], (char *) NULL); return TCL_ERROR; } for (i = 0; i < vgp->Npoly; i++) { if (vgp->poly[i].id == polyid) { appendpoint(interp, center(vgp->poly[i].boundary.ps, vgp->poly[i].boundary.pn)); return TCL_OK; } } Tcl_AppendResult(interp, " no such polygon: ", argv[2], (char *) NULL); return TCL_ERROR; } else if ((c == 't') && (strncmp(argv[1], "triangulate", length) == 0)) { if ((argc < 2)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " id ", (char *) NULL); return TCL_ERROR; } if (sscanf(argv[2], "%d", &polyid) != 1) { Tcl_AppendResult(interp, "not an integer: ", argv[2], (char *) NULL); return TCL_ERROR; } for (i = 0; i < vgp->Npoly; i++) { if (vgp->poly[i].id == polyid) { Ptriangulate(&(vgp->poly[i].boundary), triangle_callback, vgp); return TCL_OK; } } Tcl_AppendResult(interp, " no such polygon: ", argv[2], (char *) NULL); return TCL_ERROR; } else if ((c == 'r') && (strncmp(argv[1], "rotate", length) == 0)) { if ((argc < 4)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " id alpha\"", (char *) NULL); return TCL_ERROR; } if (sscanf(argv[2], "%d", &polyid) != 1) { Tcl_AppendResult(interp, "not an integer: ", argv[2], (char *) NULL); return TCL_ERROR; } if (sscanf(argv[3], "%lg", &alpha) != 1) { Tcl_AppendResult(interp, "not an angle in radians: ", argv[3], (char *) NULL); return TCL_ERROR; } for (i = 0; i < vgp->Npoly; i++) { if (vgp->poly[i].id == polyid) { n = vgp->poly[i].boundary.pn; ps = vgp->poly[i].boundary.ps; p = center(ps, n); for (j = 0; j < n; j++) { appendpoint(interp, rotate(p, ps[j], alpha)); } return TCL_OK; } } Tcl_AppendResult(interp, " no such polygon: ", argv[2], (char *) NULL); return TCL_ERROR; } else if ((c == 's') && (strncmp(argv[1], "scale", length) == 0)) { if ((argc < 4)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " id gain\"", (char *) NULL); return TCL_ERROR; } if (sscanf(argv[2], "%d", &polyid) != 1) { Tcl_AppendResult(interp, "not an integer: ", argv[2], (char *) NULL); return TCL_ERROR; } if (sscanf(argv[3], "%lg", &gain) != 1) { Tcl_AppendResult(interp, "not a number: ", argv[3], (char *) NULL); return TCL_ERROR; } for (i = 0; i < vgp->Npoly; i++) { if (vgp->poly[i].id == polyid) { n = vgp->poly[i].boundary.pn; ps = vgp->poly[i].boundary.ps; for (j = 0; j < n; j++) { appendpoint(interp, scale(p, ps[j], gain)); } return TCL_OK; } } Tcl_AppendResult(interp, " no such polygon: ", argv[2], (char *) NULL); return TCL_ERROR; } else if ((c == 'r') && (strncmp(argv[1], "remove", length) == 0)) { if ((argc < 3)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " id\"", (char *) NULL); return TCL_ERROR; } if (sscanf(argv[2], "%d", &polyid) != 1) { Tcl_AppendResult(interp, "not an integer: ", argv[2], (char *) NULL); return TCL_ERROR; } if (remove_poly(vgp, polyid)) return TCL_OK; Tcl_AppendResult(interp, " no such polygon: ", argv[2], (char *) NULL); return TCL_ERROR; } Tcl_AppendResult(interp, "bad method \"", argv[1], "\" must be one of:", "\n\tbbox, bind, bpath, center, coords, delete, find,", "\n\tinsert, list, path, remove, rotate, scale, triangulate.", (char *) NULL); return TCL_ERROR; }