From 2f0a70f0324fdc0f9c3f55d60dd45de51f7a4545 Mon Sep 17 00:00:00 2001 From: lecoanet Date: Thu, 11 May 2000 14:07:16 +0000 Subject: Ajout des fonctions contour, fit, smooth et adaptation de la fonction coords aux polygones multi-contours. --- generic/tkZinc.c | 342 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 305 insertions(+), 37 deletions(-) (limited to 'generic/tkZinc.c') diff --git a/generic/tkZinc.c b/generic/tkZinc.c index 0dc1f21..8466880 100644 --- a/generic/tkZinc.c +++ b/generic/tkZinc.c @@ -50,6 +50,7 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " #include "Track.h" #include "Transfo.h" #include "Image.h" +#include "gpc/gpc.h" #include #include @@ -1318,6 +1319,130 @@ ParseCoordList(WidgetInfo *wi, /* *---------------------------------------------------------------------- * + * Contour -- + * + *---------------------------------------------------------------------- + */ +static int +Contour(WidgetInfo *wi, + int argc, + Arg *args) +{ + ZnPoint *points; + ZnPoint p[4], xp[4]; + Item item, shape; + int cmd, num_points, num, i; + ZnBool simple; + ZnPoly poly; + char c; + ZnTransfo t, inv; + ZnContour *contours; + + num = ZnItemsWithTagOrId(wi, LangString(args[2]), &item, NULL); + if (num == 0) { + return ZN_ERROR; + } + if (!item->class->Contour) { + Tcl_AppendResult(wi->interp, "class: \"", item->class->name, + "\" doesn't handle the contour method", NULL); + return ZN_ERROR; + } + + c = LangString(args[3])[0]; + if ((c == 'd') && (strcmp(LangString(args[3]), "diff") == 0)) { + cmd = GPC_DIFF; + } + else if ((c == 'i') && (strcmp(LangString(args[3]), "inter") == 0)) { + cmd = GPC_INT; + } + else if ((c == 'u') && (strcmp(LangString(args[3]), "union") == 0)) { + cmd = GPC_UNION; + } + else if ((c == 'x') && (strcmp(LangString(args[3]), "xor") == 0)) { + cmd = GPC_XOR; + } + else { + Tcl_AppendResult(wi->interp, "unknown contour operation: \"", + LangString(args[3]), + "\" should be diff/inter/union/xor", NULL); + return ZN_ERROR; + } + + num = ZnItemsWithTagOrId(wi, LangString(args[4]), &shape, NULL); + if (num == 0) { + Tcl_ResetResult(wi->interp); + if (ParseCoordList(wi, args[4], &points, &num_points) == ZN_ERROR) { + return ZN_ERROR; + } + POLY_CONTOUR1(&poly, points, num_points); + } + else { + /* + * If something has changed in the geometry we need to + * update or the shape will be erroneous. + */ + ITEM_P.Update(wi); + if (!shape->class->GetClipVertices) { + Tcl_AppendResult(wi->interp, "class: \"", shape->class->name, + "\" can't give a polygonal shape", NULL); + return ZN_ERROR; + } + simple = shape->class->GetClipVertices(shape, &poly); + if (poly.num_contours == 0) { + return ZN_OK; + } + /* + * Compute the tranform to map the device points + * into the coordinate space of item. + */ + ITEM.GetItemTransform(item, &t); + ZnTransfoInvert(&t, &inv); + /* + * Make a new transformed poly. + */ + if (simple) { + p[0] = poly.contours[0].points[0]; + p[2] = poly.contours[0].points[1]; + p[1].x = p[2].x; + p[1].y = p[0].y; + p[3].x = p[0].x; + p[3].y = p[2].y; + ZnTransformPoints(&inv, p, xp, 4); + poly.contours[0].points = xp; + poly.contours[0].num_points = 4; + } + else { + if (poly.num_contours != 1) { + contours = poly.contours; + poly.contours = (ZnContour *) ZnMalloc(poly.num_contours*sizeof(ZnContour)); + } + else { + contours = poly.contours; + poly.contours = &poly.contour1; + } + for (i = 0; i < poly.num_contours; i++) { + points = contours[i].points; + num_points = contours[i].num_points; + poly.contours[i].num_points = num_points; + poly.contours[i].points = (ZnPoint *) ZnMalloc(num_points*sizeof(ZnPoint)); + ZnTransformPoints(&inv, points, poly.contours[i].points, num_points); + } + } + } + + item->class->Contour(item, cmd, &poly); + + if (!simple) { + POLY_FREE(&poly); + } + + return ZN_OK; +} + + +/* + *---------------------------------------------------------------------- + * * Coords -- * *---------------------------------------------------------------------- @@ -1331,7 +1456,7 @@ Coords(WidgetInfo *wi, Item item; int num_points, num = 0, i; int cmd = COORDS_READ; - long index; + long index, contour = 0; char *end, c; char msg[INTEGER_SPACE]; @@ -1341,11 +1466,11 @@ Coords(WidgetInfo *wi, } num_points = 0; if (argc == 3) { - /* Get all coords. */ - cmd = COORDS_READ_ALL; - if (item->class->Coords(item, 0, cmd, &points, &num_points) == ZN_ERROR) { + /* Get all coords of default contour (0). */ + if (item->class->Coords(item, 0, 0, COORDS_READ_ALL, &points, &num_points) == ZN_ERROR) { return ZN_ERROR; } + coords_read: for (i = 0; i < num_points; i++, points++) { sprintf(msg, "%g", points->x); Tcl_AppendElement(wi->interp, msg); @@ -1355,30 +1480,43 @@ Coords(WidgetInfo *wi, return ZN_OK; } + /* + * See if it is an ADD or REMOVE op. + */ i = 3; c = LangString(args[i])[0]; if ((c == 'a') && (strcmp(LangString(args[i]), "add") == 0)) { - if ((argc != 5) && (argc != 6)) { + if ((argc < 5) || (argc > 7)) { Tcl_AppendResult(wi->interp, "wrong # args: should be \"", LangString(args[0]), - "\" coords tagOrId add ?index? coordList", NULL); + "\" coords tagOrId add ?contour? ?index? coordList", NULL); return ZN_ERROR; } cmd = COORDS_ADD; i++; } else if ((c == 'r') && (strcmp(LangString(args[i]), "remove") == 0)) { - if (argc != 5) { + if ((argc != 5) && (argc != 6)) { Tcl_AppendResult(wi->interp, "wrong # args: should be \"", LangString(args[0]), - "\" coords tagOrId remove index", NULL); + "\" coords tagOrId remove ?contour? index", NULL); return ZN_ERROR; } cmd = COORDS_REMOVE; i++; } - - index = strtol(LangString(args[i]), &end, 10); + + /* + * Try to see if the next param is a vertex index, + * a contour index or a coord list. + */ + contour = index = strtol(LangString(args[i]), &end, 10); if (*end != '\0') { - if (((argc == 5) && (cmd != COORDS_ADD)) || (argc == 6)) { + if (((argc == 5) && (cmd != COORDS_ADD) && (cmd != COORDS_REMOVE)) || + (argc == 6) || (argc == 7)) { + Tcl_AppendResult(wi->interp, " incorrect contour index \"", + args[i], "\"", NULL); + return ZN_ERROR; + } + else if ((argc == 5) && (cmd != COORDS_ADD)) { Tcl_AppendResult(wi->interp, " incorrect coord index \"", args[i], "\"", NULL); return ZN_ERROR; @@ -1387,47 +1525,97 @@ Coords(WidgetInfo *wi, return ZN_ERROR; } if (cmd == COORDS_ADD) { - /* Append coords. */ - cmd = COORDS_ADD_LAST; - if (item->class->Coords(item, 0, cmd, &points, &num_points) == ZN_ERROR) { + /* Append coords at end of default contour (0). */ + if (item->class->Coords(item, 0, 0, COORDS_ADD_LAST, + &points, &num_points) == ZN_ERROR) { return ZN_ERROR; } } else { - /* Set all coords. */ - cmd = COORDS_REPLACE_ALL; - if (item->class->Coords(item, 0, cmd, &points, &num_points) == ZN_ERROR) { + /* Set all coords of default contour (0). */ + if (item->class->Coords(item, 0, 0, COORDS_REPLACE_ALL, + &points, &num_points) == ZN_ERROR) { return ZN_ERROR; } } return ZN_OK; } - - if (argc == (i+2)) { - /* Set a single coord or add coords at index. */ - if (ParseCoordList(wi, args[i+1], &points, &num_points) == ZN_ERROR) { + if (argc == 4) { + /* Get all coords of contour. */ + if (item->class->Coords(item, contour, 0, COORDS_READ_ALL, + &points, &num_points) == ZN_ERROR) { return ZN_ERROR; } - if (argc == 5) { - num_points = 1; - cmd = COORDS_REPLACE; + goto coords_read; + } + else if ((argc == 5) && (cmd == COORDS_REMOVE)) { + /* Remove coord at index in default contour (0). */ + if (item->class->Coords(item, 0, index, COORDS_REMOVE, + &points, &num_points) == ZN_ERROR) { + return ZN_ERROR; } - if (item->class->Coords(item, index, cmd, &points, &num_points) == ZN_ERROR) { + return ZN_OK; + } + + /* + * Try to see if the next param is a vertex index or a coord list. + */ + i++; + index = strtol(LangString(args[i]), &end, 10); + if (*end != '\0') { + if ((argc == 7) || ((argc == 6) && (cmd != COORDS_ADD))) { + Tcl_AppendResult(wi->interp, " incorrect coord index \"", + args[i], "\"", NULL); + return ZN_ERROR; + } + else if (ParseCoordList(wi, args[i], &points, &num_points) == ZN_ERROR) { return ZN_ERROR; } + if (cmd == COORDS_ADD) { + /* Append coords at end of contour. */ + if (item->class->Coords(item, contour, 0, COORDS_ADD_LAST, + &points, &num_points) == ZN_ERROR) { + return ZN_ERROR; + } + } + else { + /* Set all coords of contour. */ + if (item->class->Coords(item, contour, 0, COORDS_REPLACE_ALL, + &points, &num_points) == ZN_ERROR) { + return ZN_ERROR; + } + } + return ZN_OK; } - else { - /* Read a single coord or remove a coord. */ - if (item->class->Coords(item, index, cmd, &points, &num_points) == ZN_ERROR) { + if (argc == 5) { + /* Get coord of contour at index. */ + if (item->class->Coords(item, contour, index, COORDS_READ, + &points, &num_points) == ZN_ERROR) { return ZN_ERROR; } - if (num_points) { - sprintf(msg, "%g", points->x); - Tcl_AppendElement(wi->interp, msg); - sprintf(msg, "%g", points->y); - Tcl_AppendElement(wi->interp, msg); + goto coords_read; + } + else if ((argc == 6) && (cmd == COORDS_REMOVE)) { + /* Remove coord of contour at index. */ + if (item->class->Coords(item, contour, index, COORDS_REMOVE, + &points, &num_points) == ZN_ERROR) { + return ZN_ERROR; } + return ZN_OK; + } + + /* Set a single coord or add coords at index in contour. */ + if (ParseCoordList(wi, args[i+1], &points, &num_points) == ZN_ERROR) { + return ZN_ERROR; + } + if (argc == 6) { + num_points = 1; + cmd = COORDS_REPLACE; + } + if (item->class->Coords(item, contour, index, cmd, &points, &num_points) == ZN_ERROR) { + return ZN_ERROR; } + return ZN_OK; } @@ -1832,6 +2020,21 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */ } /* + * contour + */ + else if ((c == 'c') && (strncmp(LangString(args[1]), "contour", length) == 0)) { + if (argc != 5) { + Tcl_AppendResult(interp, "wrong # args: should be \"", LangString(args[0]), + "\" contour tagOrId diff/inter/union/xor coordListOrTagOrId", + NULL); + goto error; + } + if (Contour(wi, argc, args) == ZN_ERROR) { + goto error; + } + } + + /* * coords */ else if ((c == 'c') && (strncmp(LangString(args[1]), "coords", length) == 0)) { @@ -1903,6 +2106,40 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */ } /* + * fit + */ + else if ((c == 'f') && (strncmp(LangString(args[1]), "fit", length) == 0)) { + ZnPoint *points; + int num_points; + ZnReal error; + ZnList to_points; + + if (argc != 4) { + Tcl_AppendResult(interp, + "wrong # args: should be \"", LangString(args[0]), + "\" fit coordList error", NULL); + goto error; + } + if (ParseCoordList(wi, args[2], &points, &num_points) == ZN_ERROR) { + return ZN_ERROR; + } + if (Tcl_GetDouble(interp, args[3], &error) == ZN_ERROR) { + goto error; + } + to_points = ZnListNew(32, sizeof(ZnPoint)); + FitBezier(points, num_points, error, to_points); + points = (ZnPoint *) ZnListArray(to_points); + num_points = ZnListSize(to_points); + for (i = 0; i < num_points; i++, points++) { + sprintf(msg, "%g", points->x); + Tcl_AppendElement(wi->interp, msg); + sprintf(msg, "%g", points->y); + Tcl_AppendElement(wi->interp, msg); + } + ZnListFree(to_points); + } + + /* * gettags */ else if ((c == 'g') && (strncmp(LangString(args[1]), "gettags", length) == 0)) { @@ -2370,6 +2607,36 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */ } /* + * smooth + */ + else if ((c == 's') && (strncmp(LangString(args[1]), "smooth", length) == 0)) { + ZnPoint *points; + int num_points; + ZnList to_points; + + if (argc != 3) { + Tcl_AppendResult(interp, + "wrong # args: should be \"", LangString(args[0]), + "\" smooth coordList", NULL); + goto error; + } + if (ParseCoordList(wi, args[2], &points, &num_points) == ZN_ERROR) { + return ZN_ERROR; + } + to_points = ZnListNew(32, sizeof(ZnPoint)); + SmoothPathWithBezier(points, num_points, to_points); + points = (ZnPoint *) ZnListArray(to_points); + num_points = ZnListSize(to_points); + for (i = 0; i < num_points; i++, points++) { + sprintf(msg, "%g", points->x); + Tcl_AppendElement(wi->interp, msg); + sprintf(msg, "%g", points->y); + Tcl_AppendElement(wi->interp, msg); + } + ZnListFree(to_points); + } + + /* * tapply */ else if ((c == 't') && (strncmp(LangString(args[1]), "tapply", length) == 0)) { @@ -2637,11 +2904,12 @@ WidgetCmd(ClientData client_data, /* Information about the widget. */ Tcl_AppendResult(interp, "invalid command \"", LangString(args[1]), "\": must be " "add, addtag, anchorxy, bbox, becomes, bind, cget, " - "chggroup, clone, configure, coords, currentpart, " - "dtag, find, gettags, group, hasanchors, " + "chggroup, clone, configure, contour, coords, currentpart, " + "dtag, find, fit, gettags, group, hasanchors, " "hasfields, hasparts, hastag, itemcget, " - "itemconfigure, lower, monitor, raise, remove, rotate, " - "scale, tapply, tdelete, transform, translate, " + "itemconfigure, lower, monitor, raise, " + "remove, rotate, scale, smooth, tapply, tdelete, " + "transform, translate, " "treset, trestore, tsave, type, ", NULL); goto error; } -- cgit v1.1