49#if ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 6)) || ( TCL_MAJOR_VERSION > 8)
51#ifndef Tcl_GetStringResult
52#define Tcl_GetStringResult(interp) interp->result
78 polys_append(&vgp->
poly, (
poly){.id = id});
79 poly *rv = polys_at(&vgp->
poly, polys_size(&vgp->
poly) - 1);
97 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++)
98 obs[i] = &polys_at(&vgp->
poly, i)->boundary;
100 fprintf(stderr,
"bad arrangement\n");
114 Tcl_DStringStartSublist(result);
115 for (i = 0; i < npts; i++) {
116 snprintf(buf,
sizeof(buf),
"%g", p[i].x);
117 Tcl_DStringAppendElement(result, buf);
118 snprintf(buf,
sizeof(buf),
"%g", p[i].y);
119 Tcl_DStringAppendElement(result, buf);
122 Tcl_DStringEndSublist(result);
135 Tcl_DStringInit(&scripts);
142 for (
string = before; *
string !=
'\0' && *
string !=
'%';
string++) {
145 if (
string != before) {
146 Tcl_DStringAppend(&scripts, before,
string - before);
158 Tcl_DStringAppend(&scripts, r, strlen(r));
164 Tcl_DStringAppend(&scripts, before + 1, 1);
169 if (Tcl_GlobalEval(interp, Tcl_DStringValue(&scripts)) != TCL_OK)
170 fprintf(stderr,
"%s while in binding: %s\n\n",
172 Tcl_DStringFree(&scripts);
183 snprintf(vbuf,
sizeof(vbuf),
"vgpane%" PRIu64,
237 if (sscanf(argv[0],
"%lg", &(p->
x)) != 1) {
238 Tcl_AppendResult(interp,
"invalid x coordinate: \"", argv[0],
"\"",
NULL);
241 if (sscanf(argv[1],
"%lg", &(p->
y)) != 1) {
242 Tcl_AppendResult(interp,
"invalid y coordinate: \"", argv[1],
"\"",
NULL);
252 for (
size_t i = 0; i < n; i++) {
267 return hypot(
dx,
dy);
276 beta = atan2(p.
x - c.
x, p.
y - c.
y);
277 const double sina = sin(beta +
alpha);
278 const double cosa = cos(beta +
alpha);
279 q.
x = c.
x + r * sina;
280 q.
y = c.
y - r * cosa;
288 q.
x = c.
x + gain * (p.
x - c.
x);
289 q.
y = c.
y + gain * (p.
y - c.
y);
294 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
295 if (polys_get(&vgp->
poly, i).id ==
id) {
296 free(polys_get(&vgp->
poly, i).boundary.ps);
297 for (
size_t j = i++; i < polys_size(&vgp->
poly); i++, j++) {
298 polys_set(&vgp->
poly, j, polys_get(&vgp->
poly, i));
300 polys_resize(&vgp->
poly, polys_size(&vgp->
poly) - 1, (
poly){0});
316 for (i = 0; i < vargc; i += 2) {
320 if (result != TCL_OK)
330 size_t *n_barriers) {
333 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
334 if (polys_get(&vgp->
poly, i).id == pp)
336 if (polys_get(&vgp->
poly, i).id == qp)
338 n += polys_get(&vgp->
poly, i).boundary.pn;
342 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
343 if (polys_get(&vgp->
poly, i).id == pp)
345 if (polys_get(&vgp->
poly, i).id == qp)
347 for (
size_t j = 0; j < polys_get(&vgp->
poly, i).boundary.pn; j++) {
349 if (k >= polys_get(&vgp->
poly, i).boundary.pn)
351 bar[b].
a = polys_get(&vgp->
poly, i).boundary.ps[j];
352 bar[b].
b = polys_get(&vgp->
poly, i).boundary.ps[k];
366 snprintf(buf,
sizeof(buf),
"%g", p.
x);
367 Tcl_AppendElement(interp, buf);
368 snprintf(buf,
sizeof(buf),
"%g", p.
y);
369 Tcl_AppendElement(interp, buf);
374vgpanecmd(ClientData clientData, Tcl_Interp * interp,
int argc,
380 char *
s, **vargv, vbuf[30];
389 Tcl_AppendResult(interp,
"wrong # args: should be \"",
390 " ", argv[0],
" method ?arg arg ...?\"",
NULL);
394 Tcl_AppendResult(interp,
"Invalid handle: \"", argv[0],
"\"",
NULL);
399 if (strcmp(argv[1],
"coords") == 0) {
401 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
402 " ", argv[1],
" id ?x1 y1 x2 y2...?\"",
NULL);
405 if (sscanf(argv[2],
"%d", &
polyid) != 1) {
406 Tcl_AppendResult(interp,
"not an integer: ", argv[2],
NULL);
411 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
413 const size_t n = polys_get(&vgp->
poly, i).boundary.pn;
414 for (
size_t j = 0; j < n; j++) {
420 Tcl_AppendResult(interp,
" no such polygon: ", argv[2],
NULL);
426 Tcl_SplitList(interp, argv[3], &vargc,
428 if (result != TCL_OK) {
435 if (!vargc || vargc % 2) {
436 Tcl_AppendResult(interp,
437 "There must be a multiple of two terms in the list.",
NULL);
445 Tcl_AppendResult(interp,
" no such polygon: ", argv[2],
NULL);
451 }
else if (strcmp(argv[1],
"debug") == 0) {
453 printf(
"debug output goes here\n");
456 }
else if (strcmp(argv[1],
"delete") == 0) {
460 polys_free(&vgp->
poly);
461 Tcl_DeleteCommand(interp, argv[0]);
465 }
else if (strcmp(argv[1],
"find") == 0) {
469 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
470 " ", argv[1],
" x y\"",
NULL);
475 Tcl_SplitList(interp, argv[2], &vargc,
477 if (result != TCL_OK) {
484 result =
scanpoint(interp, &vargv[0], &p);
485 if (result != TCL_OK)
489 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
490 if (
in_poly(polys_get(&vgp->
poly, i).boundary, p)) {
491 snprintf(vbuf,
sizeof(vbuf),
"%d", polys_get(&vgp->
poly, i).id);
492 Tcl_AppendElement(interp, vbuf);
497 }
else if (strcmp(argv[1],
"insert") == 0) {
501 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
502 " ", argv[1],
" x1 y1 x2 y2 ...\"",
NULL);
508 Tcl_SplitList(interp, argv[2], &vargc,
510 if (result != TCL_OK) {
518 if (!vargc || vargc % 2) {
519 Tcl_AppendResult(interp,
520 "There must be a multiple of two terms in the list.",
NULL);
527 if (result != TCL_OK)
530 snprintf(vbuf,
sizeof(vbuf),
"%d",
polyid);
531 Tcl_AppendResult(interp, vbuf,
NULL);
534 }
else if (strcmp(argv[1],
"list") == 0) {
536 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
537 snprintf(vbuf,
sizeof(vbuf),
"%d", polys_get(&vgp->
poly, i).id);
538 Tcl_AppendElement(interp, vbuf);
542 }
else if (strcmp(argv[1],
"path") == 0) {
546 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
547 " ", argv[1],
" x1 y1 x2 y2\"",
NULL);
552 Tcl_SplitList(interp, argv[2], &vargc,
554 if (result != TCL_OK) {
562 Tcl_AppendResult(interp,
563 "invalid points: should be: \"x1 y1 x2 y2\"",
NULL);
566 result =
scanpoint(interp, &vargv[0], &p);
567 if (result != TCL_OK)
569 result =
scanpoint(interp, &vargv[2], &q);
570 if (result != TCL_OK)
577 for (
size_t i = 0; i < line.
pn; i++) {
584 }
else if (strcmp(argv[1],
"bind") == 0) {
585 if (argc < 2 || argc > 4) {
586 Tcl_AppendResult(interp,
"wrong # args: should be \"",
587 argv[0],
" bind triangle ?command?\"",
NULL);
591 Tcl_AppendElement(interp,
"triangle");
594 if (strcmp(argv[2],
"triangle") == 0) {
599 Tcl_AppendResult(interp,
"unknown event \"", argv[2],
600 "\": must be one of:\n\ttriangle.",
NULL);
604 Tcl_AppendResult(interp,
s,
NULL);
607 }
else if (strcmp(argv[1],
"bpath") == 0) {
611 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
612 " ", argv[1],
" x1 y1 x2 y2\"",
NULL);
617 Tcl_SplitList(interp, argv[2], &vargc,
619 if (result != TCL_OK) {
627 Tcl_AppendResult(interp,
628 "invalid points: should be: \"x1 y1 x2 y2\"",
NULL);
632 result =
scanpoint(interp, &vargv[0], &p);
633 if (result != TCL_OK)
635 result =
scanpoint(interp, &vargv[2], &q);
636 if (result != TCL_OK)
642 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
643 poly *tpp = polys_at(&vgp->
poly, i);
654 slopes[0].
x = slopes[0].
y = 0.0;
655 slopes[1].
x = slopes[1].
y = 0.0;
656 Proutespline(barriers, n_barriers, line, slopes, &spline);
658 for (
size_t i = 0; i < spline.
pn; i++) {
664 }
else if (strcmp(argv[1],
"bbox") == 0) {
666 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
667 " ", argv[1],
" id\"",
NULL);
670 if (sscanf(argv[2],
"%d", &
polyid) != 1) {
671 Tcl_AppendResult(interp,
"not an integer: ", argv[2],
NULL);
674 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
679 for (
size_t j = 1; j < pp.
pn; j++) {
681 UR.
x = fmax(UR.
x, p.
x);
682 UR.
y = fmax(UR.
y, p.
y);
683 LL.
x = fmin(LL.
x, p.
x);
684 LL.
y = fmin(LL.
y, p.
y);
691 Tcl_AppendResult(interp,
" no such polygon: ", argv[2],
NULL);
694 }
else if (strcmp(argv[1],
"center") == 0) {
696 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
697 " ", argv[1],
" id\"",
NULL);
700 if (sscanf(argv[2],
"%d", &
polyid) != 1) {
701 Tcl_AppendResult(interp,
"not an integer: ", argv[2],
NULL);
704 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
707 polys_get(&vgp->
poly, i).boundary.pn));
711 Tcl_AppendResult(interp,
" no such polygon: ", argv[2],
NULL);
714 }
else if (strcmp(argv[1],
"triangulate") == 0) {
716 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
721 if (sscanf(argv[2],
"%d", &
polyid) != 1) {
722 Tcl_AppendResult(interp,
"not an integer: ", argv[2],
NULL);
726 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
732 Tcl_AppendResult(interp,
" no such polygon: ", argv[2],
NULL);
734 }
else if (strcmp(argv[1],
"rotate") == 0) {
736 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
737 " ", argv[1],
" id alpha\"",
NULL);
740 if (sscanf(argv[2],
"%d", &
polyid) != 1) {
741 Tcl_AppendResult(interp,
"not an integer: ", argv[2],
NULL);
744 if (sscanf(argv[3],
"%lg", &
alpha) != 1) {
745 Tcl_AppendResult(interp,
"not an angle in radians: ", argv[3],
NULL);
748 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
750 const size_t n = polys_get(&vgp->
poly, i).boundary.pn;
751 ps = polys_get(&vgp->
poly, i).boundary.ps;
753 for (
size_t j = 0; j < n; j++) {
759 Tcl_AppendResult(interp,
" no such polygon: ", argv[2],
NULL);
762 }
else if (strcmp(argv[1],
"scale") == 0) {
764 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
765 " ", argv[1],
" id gain\"",
NULL);
768 if (sscanf(argv[2],
"%d", &
polyid) != 1) {
769 Tcl_AppendResult(interp,
"not an integer: ", argv[2],
NULL);
772 if (sscanf(argv[3],
"%lg", &gain) != 1) {
773 Tcl_AppendResult(interp,
"not a number: ", argv[3],
NULL);
776 for (
size_t i = 0; i < polys_size(&vgp->
poly); i++) {
778 const size_t n = polys_get(&vgp->
poly, i).boundary.pn;
779 ps = polys_get(&vgp->
poly, i).boundary.ps;
781 for (
size_t j = 0; j < n; j++) {
787 Tcl_AppendResult(interp,
" no such polygon: ", argv[2],
NULL);
790 }
else if (strcmp(argv[1],
"remove") == 0) {
792 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
793 " ", argv[1],
" id\"",
NULL);
796 if (sscanf(argv[2],
"%d", &
polyid) != 1) {
797 Tcl_AppendResult(interp,
"not an integer: ", argv[2],
NULL);
804 Tcl_AppendResult(interp,
" no such polygon: ", argv[2],
NULL);
808 Tcl_AppendResult(interp,
"bad method \"", argv[1],
809 "\" must be one of:",
810 "\n\tbbox, bind, bpath, center, coords, delete, find,",
811 "\n\tinsert, list, path, remove, rotate, scale, triangulate.",
NULL);
816vgpane(ClientData clientData, Tcl_Interp * interp,
int argc,
char *argv[])
825 assert(vbuf !=
NULL);
828 vgp->
poly = (polys_t){0};
833 Tcl_AppendResult(interp, vbuf,
NULL);
842 if (Tcl_InitStubs(interp, TCL_VERSION, 0) ==
NULL) {
846 if (Tcl_PkgRequire(interp,
"Tcl", TCL_VERSION, 0) ==
NULL) {
852 char adjusted_version[
sizeof(PACKAGE_VERSION)] = PACKAGE_VERSION;
853 char *tilde_dev = strstr(adjusted_version,
"~dev.");
854 if (tilde_dev !=
NULL) {
856 memmove(tilde_dev + 1, tilde_dev + strlen(
"~dev."),
857 strlen(tilde_dev + strlen(
"~dev.")) + 1);
859 if (Tcl_PkgProvide(interp,
"Tclpathplan", adjusted_version) != TCL_OK) {
863 Tcl_CreateCommand(interp,
"vgpane",
vgpane, (ClientData)
NULL,
NULL);
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static char * agxbdisown(agxbuf *xb)
Memory allocation wrappers that exit on failure.
static char * gv_strdup(const char *original)
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
vconfig_t * Pobsopen(Ppoly_t **obs, int n_obs)
void Pobsclose(vconfig_t *config)
void Pobspath(vconfig_t *config, Ppoint_t p0, int poly0, Ppoint_t p1, int poly1, Ppolyline_t *output_route)
bool in_poly(Ppoly_t poly, Ppoint_t q)
int Plegal_arrangement(Ppoly_t **polys, int n_polys)
#define DEFINE_LIST(name, type)
void make_CW(Ppoly_t *poly)
NEATOPROCS_API void s1(graph_t *, node_t *)
int Proutespline(Pedge_t *barriers, size_t n_barriers, Ppolyline_t input_route, Pvector_t endpoint_slopes[2], Ppolyline_t *output_route)
entryHeader_pt tclhandleAlloc(tblHeader_pt headerPtr, char **handle, uint64_t *entryIdxPtr)
void * tclhandleXlate(tblHeader_pt tblHdrPtr, char *handle)
void * tclhandleFree(tblHeader_pt tblHdrPtr, char *handle)
tblHeader_pt tclhandleInit(char *prefix, uint64_t entrySize, uint64_t initEntries)
static void vc_stale(vgpane_t *vgp)
static int insert_poly(Tcl_Interp *interp, vgpane_t *vgp, int id, char *vargv[], int vargc)
static int vgpanecmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
int Tclpathplan_Init(Tcl_Interp *interp)
static char * buildBindings(char *s1, const char *s2)
static int vc_refresh(vgpane_t *vgp)
static poly * allocpoly(vgpane_t *vgp, int id, int npts)
static int scanpoint(Tcl_Interp *interp, char *argv[], point *p)
static void appendpoint(Tcl_Interp *interp, point p)
static point scale(point c, point p, double gain)
static void triangle_callback(void *vgparg, point pqr[])
int Tclpathplan_SafeInit(Tcl_Interp *interp)
static void make_barriers(vgpane_t *vgp, int pp, int qp, Pedge_t **barriers, size_t *n_barriers)
static int vgpane(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
static void expandPercentsEval(Tcl_Interp *interp, char *before, char *r, int npts, point *ppos)
static point center(point vertex[], size_t n)
static void dgsprintxy(Tcl_DString *result, int npts, point p[])
static double distance(point p, point q)
static point rotate(point c, point p, double alpha)
#define Tcl_GetStringResult(interp)
static bool remove_poly(vgpane_t *vgp, int id)
TRI_API int Ptriangulate(Ppoly_t *polygon, void(*fn)(void *closure, Ppoint_t tri[]), void *vc)