~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to dag/ddspline.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <dag.h>
 
2
#include <pathplan.h>
 
3
 
 
4
#ifdef DMALLOC
 
5
#include "dmalloc.h"
 
6
#endif
 
7
 
 
8
/*
 
9
 * return polygon for a given route 
 
10
 */
 
11
 
 
12
#ifndef DONOTDEBUGANYMORE
 
13
void printregion( Ppoly_t                       *region)
 
14
{
 
15
        int     i;
 
16
 
 
17
        fprintf(stderr,"%%!PS\nnewpath\n");
 
18
        fprintf(stderr,"100 100 translate .5 .5 scale\n");
 
19
        for (i = 0; i < region->pn; i++) 
 
20
                fprintf(stderr,"%lf %lf %s\n",region->ps[i].x,region->ps[i].y,
 
21
                        (i ==0? "moveto" : "lineto"));
 
22
        fprintf(stderr,"closepath stroke showpage\n");
 
23
}
 
24
#endif
 
25
 
 
26
typedef struct tmproute_s {
 
27
        ilcurve_t bound[2];     /* left and right sides of region */
 
28
} tmproute_t;
 
29
 
 
30
#define LEFT 0
 
31
#define RIGHT 1
 
32
 
 
33
static ilcoord_t c(double x, double y) {ilcoord_t rv; rv.x = x; rv.y = y; return rv;}
 
34
 
 
35
static ilcurve_t *get_unclipped_curve(Agedge_t *e)
 
36
{
 
37
        return dd_path(e)->unclipped_path;
 
38
}
 
39
 
 
40
static Ppoly_t *allocpoly(Agraph_t *g, int npts)
 
41
{
 
42
        Ppoly_t *rv;
 
43
 
 
44
        rv = agalloc(g,sizeof(Ppoly_t));
 
45
        rv->ps = agalloc(g,sizeof(Ppoint_t)*npts);
 
46
        return rv;
 
47
}
 
48
 
 
49
static void freepoly(Agraph_t *g, Ppoly_t *poly)
 
50
{
 
51
        agfree(g,poly->ps);
 
52
        agfree(g,poly);
 
53
}
 
54
 
 
55
/* get the spacing box below rank r */
 
56
static double y_below(ddview_t *view, int r, double fract) /* from top */
 
57
{
 
58
        rank_t          *rd;
 
59
        double          val;
 
60
 
 
61
        rd = dd_rankd(view,r);
 
62
        val = rd->y_base + rd->delta_below + fract * rd->space_below;
 
63
        return val;
 
64
}
 
65
 
 
66
static ilbool local_crossing(Agnode_t *v, Agnode_t *w)
 
67
{
 
68
        int                     vw_order,vvww_order,i,pass,pathlen;
 
69
        Agnode_t        *vv,*ww;
 
70
        Agedge_t        *(*f)(Agnode_t *);
 
71
 
 
72
        pathlen = 2;
 
73
        vw_order = dd_order(w) - dd_order(v);
 
74
        ww = w;
 
75
        vv = v;
 
76
        for (pass = 0; pass < 2; pass++) {
 
77
                f = (pass == 0? agfstin: agfstout);
 
78
                for (i = 0; i < pathlen; i++) {
 
79
                        if (NOT(dd_is_a_vnode(vv))) break;
 
80
                        if (NOT(dd_is_a_vnode(ww))) break;
 
81
                        vv = f(vv)->node;
 
82
                        ww = f(ww)->node;
 
83
                        vvww_order = dd_order(ww) - dd_order(vv);
 
84
                        if (vw_order * vvww_order < 0) return TRUE;
 
85
                }
 
86
        }
 
87
        return FALSE;
 
88
}
 
89
 
 
90
static Agnode_t *bounding_node(ddview_t *view, Agnode_t *inp, int dir)
 
91
{
 
92
        Agnode_t        *v,*w;
 
93
 
 
94
        v = inp;
 
95
        while ((w = dd_relnode(view,v,dir))) {
 
96
                if (NOT(dd_is_a_vnode(w))) break;
 
97
/* just did this for testing */
 
98
break;
 
99
                if (NOT(local_crossing(v,w))) break;
 
100
                v = w;
 
101
        }
 
102
        return w;
 
103
}
 
104
 
 
105
static double dd_bound(ddview_t *view, Agnode_t *u, int side)
 
106
{
 
107
        double          rv;
 
108
        double          sep;
 
109
        Agnode_t        *w;
 
110
 
 
111
        assert(BASE(view)->bb.valid);
 
112
        sep = il_nodesep(BASE(view)).x/2.0;
 
113
        switch(side) {
 
114
        case RIGHT:
 
115
                if ((w = bounding_node(view,u,1)))
 
116
                        rv = dd_pos(w).x - dd_nodesize(view,w).x/2.0 - sep;
 
117
                else rv = BASE(view)->bb.size.ur.x;
 
118
                break;
 
119
        case LEFT:  
 
120
                if ((w = bounding_node(view,u,-1)))
 
121
                        rv = dd_pos(w).x + dd_nodesize(view,w).x/2.0 + sep;
 
122
                else rv = BASE(view)->bb.size.ll.x;
 
123
                break;
 
124
        default: 
 
125
                rv = 0.0;
 
126
                abort();
 
127
        }
 
128
        return rv;
 
129
}
 
130
 
 
131
static void append_vnode(tmproute_t *route, ddview_t *view, Agnode_t *virt);
 
132
#if 0 /* not used */
 
133
static void append_curve(tmproute_t *, int side, ilcurve_t *curve, double y0, double y1);
 
134
#endif
 
135
static void append_side(tmproute_t *, int side, double x, double y0, double y1);
 
136
static void append_point(tmproute_t *, int side, double x, double y);
 
137
static void append_box(tmproute_t *rp, ddview_t *view, int toprank, double f0, double f1);
 
138
static Agedge_t *neighboring_edge(ddview_t *view, Agnode_t *n, Agedge_t *e, int side);
 
139
static void term_route(tmproute_t *rv, ddview_t *view, Agnode_t *n,
 
140
        Agedge_t *e, ilcoord_t port, double fract);
 
141
static Ppoly_t *define_boundary_poly(Agraph_t *g, tmproute_t *tmp);
 
142
 
 
143
static tmproute_t *tmproute(Agraph_t *g, int npts)
 
144
{
 
145
        tmproute_t      *rv;
 
146
        int                     i;
 
147
 
 
148
        rv = agalloc(g,sizeof(tmproute_t));
 
149
        for (i = 0; i < 2; i++) {
 
150
                rv->bound[i].n = 0;
 
151
                rv->bound[i].p = agalloc(g,npts * sizeof(ilcoord_t));
 
152
        }
 
153
        return rv;
 
154
}
 
155
 
 
156
static void term_route(tmproute_t *rv, ddview_t *view, Agnode_t *n, Agedge_t *e, ilcoord_t port, double fract)
 
157
{
 
158
        int                     r,rb;
 
159
        double          y_cept;
 
160
        double          leftx_port, leftx_cept, rightx_port, rightx_cept;
 
161
        Agedge_t        *ne;
 
162
        ilcurve_t       *curve;
 
163
 
 
164
        r = dd_rank(n);
 
165
        if (n == agtail(e)) {rb = r; e = AGMKOUT(e);}
 
166
        else {rb = r - 1; e = AGMKIN(e);}
 
167
 
 
168
        y_cept = y_below(view,rb,fract);
 
169
 
 
170
        if ((ne = neighboring_edge(view,n,e,LEFT)) && (curve = get_unclipped_curve(ne))) {
 
171
                leftx_port = il_intersect_at_y(curve,port.y).x;
 
172
                leftx_cept = il_intersect_at_y(curve,y_cept).x;
 
173
        }
 
174
        else {
 
175
                leftx_port = leftx_cept = dd_bound(view,n,LEFT);
 
176
        }
 
177
 
 
178
        if ((ne = neighboring_edge(view,n,e,RIGHT)) && (curve = get_unclipped_curve(ne))) {
 
179
                rightx_port = il_intersect_at_y(curve,port.y).x;
 
180
                rightx_cept = il_intersect_at_y(curve,y_cept).x;
 
181
        }
 
182
        else {
 
183
                rightx_port = rightx_cept = dd_bound(view,n,RIGHT);
 
184
        }
 
185
 
 
186
        if (leftx_port > rightx_port)
 
187
                {double t = leftx_port; leftx_port = rightx_port; rightx_port = t;}
 
188
 
 
189
        if (leftx_cept > rightx_cept)
 
190
                {double t = leftx_cept; leftx_cept = rightx_cept; rightx_cept = t;}
 
191
 
 
192
        if (port.y < y_cept) {
 
193
                append_point(rv, LEFT, leftx_port, port.y);
 
194
                append_point(rv, LEFT, leftx_cept, y_cept);
 
195
                append_point(rv, RIGHT, rightx_port, port.y);
 
196
                append_point(rv, RIGHT, rightx_cept, y_cept);
 
197
        }
 
198
        else {
 
199
                append_point(rv, LEFT, leftx_cept, y_cept);
 
200
                append_point(rv, LEFT, leftx_port, port.y);
 
201
                append_point(rv, RIGHT, rightx_cept, y_cept);
 
202
                append_point(rv, RIGHT, rightx_port, port.y);
 
203
        }
 
204
}
 
205
 
 
206
static Agedge_t *neighboring_edge(ddview_t *view, Agnode_t *n, Agedge_t *e, int side)
 
207
{
 
208
        Agedge_t        *f,*rv;
 
209
#ifdef NEIGHBORING_EDGE
 
210
        int                     delta,delta0, dir;
 
211
#endif
 
212
 
 
213
        if (AGTYPE(e) == AGINEDGE) f = agfstin(aghead(e));
 
214
        else f = agfstout(agtail(e));
 
215
 
 
216
        rv = NILedge;
 
217
#ifdef NEIGHBORING_EDGE
 
218
        if (side == LEFT) dir = -1; else dir = 1;
 
219
        delta0 = 0;
 
220
        while (f) {
 
221
                if (f != e) {
 
222
                        if (dd_espec(f)->pos) {
 
223
                                delta = dd_order(f->node) - dd_order(e->node);
 
224
                                if (delta * dir > 0) {
 
225
                                        delta = abs(delta);
 
226
                                        if ((rv == NILedge) || (delta < delta0)) {
 
227
                                                rv = f;
 
228
                                                delta0 = delta;
 
229
                                        }
 
230
                                }
 
231
                        }
 
232
                }
 
233
                if (AGTYPE(e) == AGINEDGE) f = agnxtin(f);
 
234
                else f = agnxtout(f);
 
235
        }
 
236
#endif
 
237
        return rv;
 
238
}
 
239
 
 
240
#if 0 /* not used */
 
241
static void append_curve(tmproute_t *rp, int side, ilcurve_t *curve, double y0, double y1)
 
242
{
 
243
        int             i;
 
244
 
 
245
        if (y0 > y1) {double temp = y0; y0 = y1; y1 = temp;}
 
246
        i = rp->bound[side].n;
 
247
        rp->bound[side].n += 2;
 
248
        rp->bound[side].p[i++] = il_intersect_at_y(curve,y0);
 
249
        rp->bound[side].p[i++] = il_intersect_at_y(curve,y1);
 
250
}
 
251
#endif
 
252
 
 
253
static void add_extrema(tmproute_t *rp, ddview_t *view, double y)
 
254
{
 
255
        int             i;
 
256
        i = rp->bound[LEFT].n++;
 
257
        rp->bound[LEFT].p[i] = c(BASE(view)->bb.size.ll.x,y);
 
258
        i = rp->bound[RIGHT].n++;
 
259
        rp->bound[RIGHT].p[i] = c(BASE(view)->bb.size.ur.x,y);
 
260
}
 
261
 
 
262
static void append_box(tmproute_t *rp, ddview_t *view, int toprank, double f0, double f1)
 
263
{
 
264
        double          y;
 
265
 
 
266
        y = y_below(view, toprank, f0);
 
267
        add_extrema(rp,view,y);
 
268
        y = y_below(view, toprank, f1);
 
269
        add_extrema(rp,view,y);
 
270
}
 
271
 
 
272
static void append_side(tmproute_t *rp, int side, double x, double arg_y0, double arg_y1)
 
273
{
 
274
        int             i;
 
275
        double  y0,y1;
 
276
 
 
277
        if (arg_y0 < arg_y1) {y0 = arg_y0; y1 = arg_y1;}
 
278
        else {y0 = arg_y1; y1 = arg_y0;}
 
279
        i = rp->bound[side].n;
 
280
        rp->bound[side].n += 2;
 
281
        rp->bound[side].p[i++] = c(x,y0);
 
282
        rp->bound[side].p[i++] = c(x,y1);
 
283
}
 
284
 
 
285
static void append_point(tmproute_t *rp, int side, double x, double y)
 
286
{
 
287
        int             i;
 
288
 
 
289
        i = rp->bound[side].n++;
 
290
        rp->bound[side].p[i].x = x;
 
291
        rp->bound[side].p[i].y = y;
 
292
}
 
293
 
 
294
/* this appends the part of the path needed to route through a vnode box */
 
295
static void append_vnode(tmproute_t *route, ddview_t *view, Agnode_t *virt)
 
296
{
 
297
        int             r;
 
298
        double  top_y, bot_y, left_x, right_x;
 
299
 
 
300
        r = dd_rank(virt);
 
301
        top_y = y_below(view,r-1,1.0);
 
302
        bot_y = y_below(view,r,0.0);
 
303
        left_x = dd_bound(view, virt, LEFT);
 
304
        right_x = dd_bound(view, virt, RIGHT);
 
305
assert(left_x < right_x);
 
306
        append_side(route,LEFT,left_x,top_y, bot_y);
 
307
        append_side(route,RIGHT,right_x,top_y, bot_y);
 
308
}
 
309
 
 
310
static Ppoint_t pppoint(double x, double y)
 
311
        {Ppoint_t rv; rv.x = x; rv.y = y; return rv;}
 
312
 
 
313
static Ppoint_t cvtpt(ilcoord_t p)
 
314
        {Ppoint_t rv; rv.x = (double)p.x; rv.y = (double)p.y; return rv;}
 
315
 
 
316
static ilcoord_t uncvtpt(Ppoint_t p)
 
317
        {ilcoord_t rv; rv.x = p.x; rv.y = p.y; return rv;}
 
318
 
 
319
static ilcoord_t addpt(ilcoord_t p, ilcoord_t q)
 
320
        {ilcoord_t rv; rv.x = p.x + q.x; rv.y = p.y + q.y; return rv;}
 
321
 
 
322
static ilbool pt_eq(Ppoint_t p, Ppoint_t q)
 
323
{
 
324
        return ((p.x == q.x) && (p.y == q.y));
 
325
}
 
326
 
 
327
/* destructive conversion */
 
328
static Ppoly_t *define_boundary_poly(Agraph_t *g, tmproute_t *tmp)
 
329
{
 
330
        Ppoly_t         *rv;
 
331
        int                     i,j,max_npts;
 
332
 
 
333
        max_npts = tmp->bound[0].n + tmp->bound[1].n;
 
334
        rv = allocpoly(g,max_npts);
 
335
        j = 0;
 
336
        for (i = 0; i < tmp->bound[0].n; i++)
 
337
                if ((j == 0) || !pt_eq(rv->ps[j-1],cvtpt(tmp->bound[0].p[i])))
 
338
                        rv->ps[j++] = cvtpt(tmp->bound[0].p[i]);
 
339
        for (i = tmp->bound[1].n - 1; i >= 0; i--)
 
340
                if ((j == 0) || !pt_eq(rv->ps[j-1],cvtpt(tmp->bound[1].p[i])))
 
341
                        rv->ps[j++] = cvtpt(tmp->bound[1].p[i]);
 
342
        rv->pn = j;
 
343
        agfree(g,tmp->bound[0].p);
 
344
        agfree(g,tmp->bound[1].p);
 
345
        agfree(g,tmp);
 
346
        return rv;
 
347
}
 
348
 
 
349
Ppoly_t *dd_forward_edge_region(ddview_t *view, Agnode_t *tl, Agnode_t *hd,Agedge_t **inp, ilcoord_t tp, ilcoord_t hp)
 
350
{
 
351
        int                     i,r;
 
352
        tmproute_t      *route;
 
353
        double          prev_fract;
 
354
        Ppoly_t         *rv;
 
355
 
 
356
        r = dd_rank(tl);
 
357
        /* 2 points for each vnode side, 2 points for each inter-rank box side,
 
358
           plus 5 for head and 5 for tail termination */
 
359
        route = tmproute(view->layout, (dd_rank(hd) - r)*4 + 10); 
 
360
        
 
361
        prev_fract = .3;
 
362
        term_route(route,view,tl,inp[0],tp,prev_fract);
 
363
 
 
364
        for (i = 0; inp[i+1]; i++) {
 
365
                append_box(route,view,r++,prev_fract,1.0);
 
366
                append_vnode(route,view,inp[i]->node);
 
367
                prev_fract = 0.0;
 
368
        }
 
369
 
 
370
        append_box(route,view,r++,prev_fract,.7);
 
371
        term_route(route,view,hd,inp[i],hp,.7);
 
372
 
 
373
        rv = define_boundary_poly(view->layout,route);
 
374
        return rv;
 
375
}
 
376
 
 
377
Ppoly_t *dd_flat_edge_region(ddview_t *view, Agnode_t *tl, Agnode_t *hd, ilcoord_t tp, ilcoord_t hp)
 
378
{
 
379
        int                     i, ix, n_obstacles;
 
380
        double          xleft, xright, y;
 
381
        Agnode_t        *left, *right, *obstacle;
 
382
        ilcoord_t       lp,rp,size;
 
383
        rank_t          *rd;
 
384
        Ppoly_t         *rv;
 
385
 
 
386
        if (dd_order(tl) < dd_order(hd)) {left = tl;  right = hd; lp = tp; rp = hp;}
 
387
        else {left = hd; right = tl; lp = hp; rp = tp;}
 
388
        n_obstacles = dd_order(right) - dd_order(left) - 1;
 
389
        rv = allocpoly(view->layout,4 + n_obstacles * 2);
 
390
        rd = dd_rankd(view,dd_rank(tl));
 
391
 
 
392
        /* walk along bottom */
 
393
        ix = 0;
 
394
        if (n_obstacles == 0) {
 
395
                y = rd->y_base + rd->delta_below;
 
396
                rv->ps[ix++] = pppoint(lp.x,y);
 
397
                rv->ps[ix++] = pppoint(rp.x,y);
 
398
        }
 
399
        else {
 
400
                rv->ps[ix++] = cvtpt(lp);
 
401
                obstacle = left;
 
402
                for (i = 0; i < n_obstacles; i++) {
 
403
                        obstacle = dd_right(view,obstacle);
 
404
                        size = dd_nodesize(view,obstacle);
 
405
                        y = rd->y_base - size.y / 2.0;
 
406
                        xleft = dd_pos(obstacle).x - size.x / 2.0;
 
407
                        xright = xleft + size.x;
 
408
                        rv->ps[ix++] = pppoint(xleft,y);
 
409
                        rv->ps[ix++] = pppoint(xright,y);
 
410
                }
 
411
                rv->ps[ix++] = cvtpt(rp);
 
412
        }
 
413
 
 
414
        /* add the top */
 
415
        y = rd->y_base - rd->delta_above - dd_ranksep(view) / 2.0; ;
 
416
        rv->ps[ix++] = pppoint(rp.x,y);
 
417
        rv->ps[ix++] = pppoint(lp.x,y);
 
418
        rv->pn = ix;
 
419
        return rv;
 
420
}
 
421
 
 
422
static void get_vnode_path(ddview_t *view, Agedge_t *view_edge, Agedge_t **result)
 
423
{
 
424
        Agedge_t        *e,*f;
 
425
        int                     i;
 
426
 
 
427
        i = 0;
 
428
        e = dd_first_elt(view_edge); 
 
429
        f = dd_last_elt(view_edge);
 
430
        while (1) {
 
431
                result[i++] = e;
 
432
                if (e == f) break;
 
433
                e = agfstout(e->node);
 
434
        }
 
435
        result[i++] = NILedge;
 
436
}
 
437
 
 
438
static void adjust_vpath(ddview_t *view, Agedge_t **vpath, ilcurve_t *curve)
 
439
{
 
440
        Agedge_t        *e;
 
441
        Agnode_t        *vnode;
 
442
        int                     i;
 
443
        double          x,y;
 
444
        double          lb,rb,halfwidth,least_move;
 
445
 
 
446
        for (i = 0; (e = vpath[i]); i++) {
 
447
                vnode = e->node;
 
448
                if (dd_is_a_vnode(vnode)) {
 
449
                        Agnode_t *left = dd_left(view, vnode);
 
450
                        Agnode_t *right = dd_right(view, vnode);
 
451
 
 
452
                        y = dd_pos(vnode).y;
 
453
                        x = il_intersect_at_y(curve, y).x;
 
454
                        halfwidth = dd_nodesize(view,vnode).x / 2.0;
 
455
                        lb = dd_bound(view,vnode,LEFT) + halfwidth;
 
456
                        if (x < lb) x = lb;
 
457
                        rb = dd_bound(view,vnode,RIGHT) - halfwidth;
 
458
                        if (x > rb) x = rb;
 
459
 
 
460
                        /* don't move if it's too small */
 
461
                        least_move = BASE(view)->client->separation.x;
 
462
                        if ((x < rb) && (x > lb) && fabs(x - dd_pos(vnode).x) >= least_move)
 
463
                                dd_set_x(vnode,x);
 
464
                        /* it's possible that local_crossing() swaps vnode order */
 
465
                        while ((left = dd_left(view, vnode))) {
 
466
                                /* for testing - should never happen right now! */
 
467
                                if (dd_pos(left).x > x){
 
468
                                        abort();dd_exchange(view,left,vnode);
 
469
                                }
 
470
                                else break;
 
471
                        }
 
472
                        while ((right = dd_right(view, vnode))) {
 
473
                                if (dd_pos(right).x < x){abort();dd_exchange(view,right,vnode);}
 
474
                                else break;
 
475
                        }
 
476
                }
 
477
        }
 
478
}
 
479
 
 
480
static void set_actual_x(ddview_t *view, ddpath_t *path)
 
481
{
 
482
        Agnode_t                *vn;
 
483
        Agedge_t                *ve;
 
484
        ilcurve_t               *curve;
 
485
        ddnode_t                *nd;
 
486
 
 
487
        curve = &(path->base.client->pos->def.curve);
 
488
        for (ve = path->first; dd_is_a_vnode(ve->node); ve = ve->node->out) {
 
489
                vn = ve->node; nd = dd_node(vn);
 
490
                nd->actual_x = il_intersect_at_y(curve,nd->cur.pos.y).x;
 
491
                nd->actual_x_valid = TRUE;
 
492
        }
 
493
}
 
494
 
 
495
void dd_make_edge_spline(ddview_t *view, ddpath_t *path)
 
496
{
 
497
        int                             i;
 
498
        Agraph_t                *layout;
 
499
        Agedge_t                *view_edge, **vpath;
 
500
        Agnode_t                *tl,*hd;
 
501
        ilcoord_t               tailpt, headpt;
 
502
        ilcurve_t               *unclipped,*clipped;
 
503
        ilbool                  reversed;
 
504
        Ppoly_t                 *region;
 
505
        Ppoint_t                endpoints[2];
 
506
        Pvector_t               endslopes[2];
 
507
        Ppolyline_t             polyline_route, spline_route;
 
508
        Ppoly_t                 *polys[1];
 
509
        Pedge_t                 *barriers;
 
510
        int                             n_barriers;
 
511
 
 
512
        assert(path->unclipped_path == NILcurve);
 
513
 
 
514
        layout = view->layout;
 
515
        tl = dd_rep(agtail(path->model));
 
516
        hd = dd_rep(aghead(path->model));
 
517
 
 
518
        reversed = (dd_rank(tl) > dd_rank(hd));
 
519
        if (reversed) {Agnode_t *temp; temp = tl; tl = hd; hd = temp;}
 
520
        tailpt = addpt(path->base.client->tail.port,dd_pos(tl));
 
521
        headpt = addpt(path->base.client->head.port,dd_pos(hd));
 
522
 
 
523
        if (tl == hd) { /* self arc */
 
524
                ilcoord_t       farpt,sep;
 
525
                double          rb;
 
526
 
 
527
                sep = view->base.client->separation;
 
528
                unclipped = il_newcurve(agheap(layout),IL_SPLINE,100);
 
529
                farpt.x = dd_pos(tl).x + dd_nodesize(view,tl).x / 2.0 + 2.0 * sep.x;
 
530
                rb = dd_bound(view, tl, RIGHT);
 
531
                if (dd_right(view,tl) == NILnode) rb += 2.0 * sep.x; /* ok to grow */
 
532
                if (farpt.x > rb) farpt.x = rb;
 
533
                farpt.y = (tailpt.y + headpt.y) / 2.0;
 
534
                unclipped->p[0] = tailpt;
 
535
                unclipped->p[1] = ilcoord(tailpt.x,tailpt.y + sep.y / 2.0);
 
536
                unclipped->p[2] = ilcoord(farpt.x,farpt.y + sep.y / 2.0);
 
537
                unclipped->p[3] = farpt;
 
538
                unclipped->p[4] = ilcoord(farpt.x,farpt.y - sep.y / 2.0);
 
539
                unclipped->p[5] = ilcoord(headpt.x,headpt.y - sep.y / 2.0);
 
540
                unclipped->p[6] = headpt;
 
541
                unclipped->n = 7;
 
542
                vpath = NIL(Agedge_t**);
 
543
        }
 
544
        else {
 
545
 
 
546
                if (dd_rank(tl) == dd_rank(hd)) {
 
547
                        region = dd_flat_edge_region(view,tl,hd,tailpt,headpt);
 
548
                        vpath = NIL(Agedge_t**);
 
549
                }
 
550
                else {
 
551
                        view_edge = path->first;
 
552
                        vpath = agalloc(layout,sizeof(Agedge_t*)*(view->config->high - view->config->low + 2));
 
553
                        get_vnode_path(view, view_edge, vpath);
 
554
                        dd_check_vnode_path(view, vpath);
 
555
                        region = dd_forward_edge_region(view,tl,hd,vpath,tailpt,headpt);
 
556
                }
 
557
 
 
558
                endpoints[0] = cvtpt(tailpt);
 
559
                endpoints[1] = cvtpt(headpt);
 
560
                endslopes[0].x = endslopes[0].y = 0.0;
 
561
                endslopes[1].x = endslopes[1].y = 0.0;
 
562
                Pshortestpath(region, endpoints, &polyline_route);
 
563
 
 
564
                polys[0] = region;
 
565
                Ppolybarriers(polys, 1, &barriers, &n_barriers);
 
566
 
 
567
                assert(!Proutespline (barriers, n_barriers, polyline_route,
 
568
                        endslopes, &spline_route));
 
569
 
 
570
 
 
571
                unclipped = il_newcurve(agheap(layout),IL_SPLINE,spline_route.pn);
 
572
                for (i = 0; i < spline_route.pn; i++)
 
573
                        unclipped->p[i] = uncvtpt(spline_route.ps[i]);
 
574
                unclipped->n = spline_route.pn;
 
575
 
 
576
                freepoly(layout,region);
 
577
                free(barriers);
 
578
                /* do not free these because they are reused by path/shortest.c */
 
579
                /* free(polyline_route.ps); free(spline_route.ps); */
 
580
        }
 
581
        path->unclipped_path = unclipped;
 
582
        clipped = il_clip_endpoints(BASE(view),unclipped, dd_nspec(tl), dd_nspec(hd));
 
583
        if (reversed) {
 
584
                for (i = 0; i < clipped->n / 2; i++) {
 
585
                        ilcoord_t t = clipped->p[i];
 
586
                        clipped->p[i] = clipped->p[clipped->n - i - 1];
 
587
                        clipped->p[clipped->n - i - 1] = t;
 
588
                }
 
589
        }
 
590
        il_freeshape(agheap(DDmodel(BASE(view)->client)),path->base.client->pos);
 
591
        path->base.client->pos =
 
592
                il_newshape(agheap(DDmodel(BASE(view)->client)),clipped,NILshape);
 
593
        if (vpath) {
 
594
                adjust_vpath(view, vpath, unclipped);
 
595
                agfree(layout,vpath);
 
596
                set_actual_x(view, path);
 
597
        }
 
598
}