Esempio n. 1
0
/* 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;
}
Esempio n. 2
0
/* 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;
}