23 static char *pf2s(
pointf p,
char *buf)
25 sprintf(buf,
"(%.5g,%.5g)", p.
x, p.
y);
47 ipp.
y = pp.
y + (
int) ((ipp.
x - ppx) * (ppy - cpy) / (ppx - cpx));
48 if (ipp.
y >= ll.
y && ipp.
y <= ur.
y)
53 ipp.
y = pp.
y + (
int) ((ipp.
x - ppx) * (ppy - cpy) / (ppx - cpx));
54 if (ipp.
y >= ll.
y && ipp.
y <= ur.
y)
59 ipp.
x = pp.
x + (
int) ((ipp.
y - ppy) * (ppx - cpx) / (ppy - cpy));
60 if (ipp.
x >= ll.
x && ipp.
x <= ur.
x)
65 ipp.
x = pp.
x + (
int) ((ipp.
y - ppy) * (ppx - cpx) / (ppy - cpy));
66 if (ipp.
x >= ll.
x && ipp.
x <= ur.
x)
72 char ppbuf[100], cpbuf[100], llbuf[100], urbuf[100];
75 "segment [%s,%s] does not intersect box ll=%s,ur=%s\n",
76 pf2s(pp, ppbuf), pf2s(cp, cpbuf),
77 pf2s(ll, llbuf), pf2s(ur, urbuf));
100 if (!cluster_name || (*cluster_name ==
'\0'))
104 agerr(
AGWARN,
"cluster named %s not found\n", cluster_name);
122 static int countVertCross(
pointf * pts,
double xcoord)
126 int num_crossings = 0;
128 sign =
CMP(pts[0].x, xcoord);
131 for (i = 1; i <= 3; i++) {
133 sign =
CMP(pts[i].x, xcoord);
134 if ((sign != old_sign) && (old_sign != 0))
137 return num_crossings;
144 static int countHorzCross(
pointf * pts,
double ycoord)
148 int num_crossings = 0;
150 sign =
CMP(pts[0].y, ycoord);
153 for (i = 1; i <= 3; i++) {
155 sign =
CMP(pts[i].y, ycoord);
156 if ((sign != old_sign) && (old_sign != 0))
159 return num_crossings;
171 findVertical(
pointf * pts,
double tmin,
double tmax,
172 double xcoord,
double ymin,
double ymax)
182 no_cross = countVertCross(pts, xcoord);
187 if ((no_cross == 1) && (fabs(pts[3].x - xcoord) <= 0.005)) {
188 if ((ymin <= pts[3].y) && (pts[3].y <= ymax)) {
195 Bezier(pts, 3, 0.5, Left, Right);
196 t = findVertical(Left, tmin, (tmin + tmax) / 2.0, xcoord, ymin, ymax);
199 return findVertical(Right, (tmin + tmax) / 2.0, tmax, xcoord, ymin,
213 findHorizontal(
pointf * pts,
double tmin,
double tmax,
214 double ycoord,
double xmin,
double xmax)
224 no_cross = countHorzCross(pts, ycoord);
229 if ((no_cross == 1) && (fabs(pts[3].y - ycoord) <= 0.005)) {
230 if ((xmin <= pts[3].x) && (pts[3].x <= xmax)) {
237 Bezier(pts, 3, 0.5, Left, Right);
238 t = findHorizontal(Left, tmin, (tmin + tmax) / 2.0, ycoord, xmin,
242 return findHorizontal(Right, (tmin + tmax) / 2.0, tmax, ycoord, xmin,
254 static int splineIntersectf(
pointf * pts,
boxf * bb)
261 for (i = 0; i < 4; i++) {
265 t = findVertical(pts, 0.0, 1.0, bb->
LL.
x, bb->
LL.
y, bb->
UR.
y);
266 if ((t >= 0) && (t < tmin)) {
270 t = findVertical(pts, 0.0,
MIN(1.0, tmin), bb->
UR.
x, bb->
LL.
y,
272 if ((t >= 0) && (t < tmin)) {
276 t = findHorizontal(pts, 0.0,
MIN(1.0, tmin), bb->
LL.
y, bb->
LL.
x,
278 if ((t >= 0) && (t < tmin)) {
282 t = findHorizontal(pts, 0.0,
MIN(1.0, tmin), bb->
UR.
y, bb->
LL.
x,
284 if ((t >= 0) && (t < tmin)) {
308 int starti = 0, endi = 0;
319 lh = getCluster(g,
agget(e,
"lhead"), clustMap);
320 lt = getCluster(g,
agget(e,
"ltail"), clustMap);
326 if (
ED_spl(e)->size > 1) {
327 agerr(
AGWARN,
"%s -> %s: spline size > 1 not supported\n",
355 agerr(
AGWARN,
"%s -> %s: head not inside head cluster %s\n",
363 if (inBoxf(bez->
list[0], bb)) {
366 "%s -> %s: tail is inside head cluster %s\n",
370 p = boxIntersectf(bez->
list[0], bez->
sp, bb);
372 bez->
list[1] = mid_pointf(p, bez->
sp);
373 bez->
list[0] = mid_pointf(bez->
list[1], bez->
sp);
374 bez->
list[2] = mid_pointf(bez->
list[1], p);
377 starti, 0, nbez, bez->
eflag);
382 for (endi = 0; endi < size - 1; endi += 3) {
383 if (splineIntersectf(&(bez->
list[endi]), bb))
386 if (endi == size - 1) {
388 nbez->
ep = boxIntersectf(bez->
ep, bez->
list[endi], bb);
393 starti, endi, nbez, bez->
eflag);
415 agerr(
AGWARN,
"%s -> %s: tail not inside tail cluster %s\n",
423 if (inBoxf(bez->
list[endi], bb)) {
426 "%s -> %s: head is inside tail cluster %s\n",
430 p = boxIntersectf(bez->
list[endi], nbez->
ep, bb);
432 bez->
list[starti] = p;
433 bez->
list[starti + 2] = mid_pointf(p, nbez->
ep);
434 bez->
list[starti + 3] = mid_pointf(bez->
list[starti + 2], nbez->
ep);
435 bez->
list[starti + 1] = mid_pointf(bez->
list[starti + 2], p);
438 endi - 3, nbez, bez->
sflag);
442 for (starti = endi; starti > 0; starti -= 3) {
443 for (i = 0; i < 4; i++)
444 pts[i] = bez->
list[starti - i];
445 if (splineIntersectf(pts, bb)) {
446 for (i = 0; i < 4; i++)
447 bez->
list[starti - i] = pts[i];
454 boxIntersectf(bez->
sp, bez->
list[starti], bb);
459 endi - 3, nbez, bez->
sflag);
473 nbez->
size = endi - starti + 1;
475 for (i = 0, j = starti; i < nbez->
size; i++, j++)
482 static void dump(
Dt_t* map)
485 fprintf (stderr,
"# in map: %d\n",
dtsize(map));
487 fprintf (stderr,
" %s\n", p->
name);
501 makeCompoundEdge(g, e, clustMap);
CDT_API int dtclose(Dt_t *)
Dt_t * mkClustMap(Agraph_t *g)
int agerr(agerrlevel_t level, const char *fmt,...)
int arrowEndClip(edge_t *e, pointf *ps, int startp, int endp, bezier *spl, int eflag)
CGRAPH_API Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
char * agget(void *obj, char *name)
CGRAPH_API Agnode_t * agtail(Agedge_t *e)
CGRAPH_API Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
CGRAPH_API char * agnameof(void *)
CDT_API int dtsize(Dt_t *)
CGRAPH_API Agnode_t * agfstnode(Agraph_t *g)
if(aagss+aagstacksize-1<=aagssp)
pointf Bezier(pointf *V, int degree, double t, pointf *Left, pointf *Right)
Agraph_t * findCluster(Dt_t *map, char *name)
void dot_compoundEdges(graph_t *g)
CGRAPH_API Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
int arrowStartClip(edge_t *e, pointf *ps, int startp, int endp, bezier *spl, int sflag)