Beispiel #1
0
point *routesplines(path * pp, int *npoints)
{
    Ppoly_t poly;
    Ppolyline_t pl, spl;
    int splinepi;
    Ppoint_t eps[2];
    Pvector_t evs[2];
    int edgei, prev, next;
    point sp[4];
    int pi, bi, si;
    double t;
    box *boxes;
    int boxn;
    edge_t* realedge;
    int flip;

    nedges++;
    nboxes += pp->nbox;

    for (realedge = (edge_t *) pp->data;
#ifdef NOTNOW
	 origedge = realedge;
#endif
	 realedge && ED_edge_type(realedge) != NORMAL;
	 realedge = ED_to_orig(realedge));
    if (!realedge) {
	agerr(AGERR, "in routesplines, cannot find NORMAL edge\n");
	abort();
    }

    boxes = pp->boxes;
    boxn = pp->nbox;

    checkpath(boxn, boxes, pp);

#ifdef DEBUG
    if (debugleveln(realedge, 1))
	printboxes(boxn, boxes);
    if (debugleveln(realedge, 3)) {
	psprintinit(1);
	psprintboxes(boxn, boxes);
    }
#endif

    if (boxn * 8 > polypointn) {
	polypoints = ALLOC(boxn * 8, polypoints, Ppoint_t);
	polypointn = boxn * 8;
    }

    if ((boxn > 1) && (boxes[0].LL.y > boxes[1].LL.y)) {
        flip = 1;
	for (bi = 0; bi < boxn; bi++) {
	    int v = boxes[bi].UR.y;
	    boxes[bi].UR.y = -1*boxes[bi].LL.y;
	    boxes[bi].LL.y = -v;
	}
    }
    else flip = 0;

    if (realedge->tail != realedge->head) {
	/* I assume that the path goes either down only or
	   up - right - down */
	for (bi = 0, pi = 0; bi < boxn; bi++) {
	    next = prev = 0;
	    if (bi > 0)
		prev = (boxes[bi].LL.y > boxes[bi - 1].LL.y) ? -1 : 1;
	    if (bi < boxn - 1)
		next = (boxes[bi + 1].LL.y > boxes[bi].LL.y) ? 1 : -1;
	    if (prev != next) {
		if (next == -1 || prev == 1) {
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		} else {
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		}
	    }
	    else if (prev == 0) { /* single box */
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].UR.y;
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].LL.y;
	    } 
	    else {
		if (!(prev == -1 && next == -1))
		    abort();
	    }
	}
	for (bi = boxn - 1; bi >= 0; bi--) {
	    next = prev = 0;
	    if (bi < boxn - 1)
		prev = (boxes[bi].LL.y > boxes[bi + 1].LL.y) ? -1 : 1;
	    if (bi > 0)
		next = (boxes[bi - 1].LL.y > boxes[bi].LL.y) ? 1 : -1;
	    if (prev != next) {
		if (next == -1 || prev == 1 ) {
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		} else {
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		}
	    } 
	    else if (prev == 0) { /* single box */
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].LL.y;
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].UR.y;
	    }
	    else {
		if (!(prev == -1 && next == -1)) {
		    /* it went badly, e.g. degenerate box in boxlist */
		    *npoints = 0;
		    abort();	/* for correctness sake, it's best to just stop */
		    return ps;	/* could also be reported as a lost edge (no spline) */
		}
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].LL.y;
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].UR.y;
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].UR.y;
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].LL.y;
	    }
	}
    } 
    else {
#ifdef OBSOLETE
	/* new, more generalized approach for self-edges.  We do not
	   assume any monotonicity about the box path, only that it
	   is simply connected.  We build up the constraint poly by
	   walking the box path from one end to the other and back
	   in the recursive function append(). A better approach to all
	   of this might be to dispense with the box paths altogether
	   and just compute the constraint poly directly, but this
	   needs to be done as part of a more thorough overhaul. */
	point p0, p1;
	box b0, b1;
	b0 = pp->boxes[0];
	b1 = pp->boxes[1];
	/* determine 'starting' segment (side of b0) for box path search */
	if (b0.UR.x == b1.LL.x) {
	    p0 = b0.LL;
	    p1 = mkpt(b0.LL.x, b0.UR.y);
	} else if (b0.LL.y == b1.UR.y) {
	    p0 = mkpt(b0.LL.x, b0.UR.y);
	    p1 = b0.UR;
	} else if (b0.LL.x == b1.UR.x) {
	    p0 = b0.UR;
	    p1 = mkpt(b0.UR.x, b0.LL.y);
	} else if (b0.UR.y == b1.LL.y) {
	    p0 = mkpt(b0.UR.x, b0.LL.y);
	    p1 = b0.LL;
	} else
	    abort();
	pi = append(pp, 0, p0, p1, 0);
#else
	abort();
#endif
    }


    if (flip) {
	int i;
	for (bi = 0; bi < boxn; bi++) {
	    int v = boxes[bi].UR.y;
	    boxes[bi].UR.y = -1*boxes[bi].LL.y;
	    boxes[bi].LL.y = -v;
	}
	for (i = 0; i < pi; i++)
	    polypoints[i].y *= -1;
    }

    for (bi = 0; bi < boxn; bi++)
	boxes[bi].LL.x = INT_MAX, boxes[bi].UR.x = INT_MIN;
    poly.ps = polypoints, poly.pn = pi;
    eps[0].x = pp->start.p.x, eps[0].y = pp->start.p.y;
    eps[1].x = pp->end.p.x, eps[1].y = pp->end.p.y;
    if (Pshortestpath(&poly, eps, &pl) == -1)
	abort();
#ifdef DEBUG
    if (debugleveln(realedge, 3)) {
	psprintpoly(poly);
	psprintline(pl);
    }
#endif
    if (poly.pn > edgen) {
	edges = ALLOC(poly.pn, edges, Pedge_t);
	edgen = poly.pn;
    }
    for (edgei = 0; edgei < poly.pn; edgei++) {
	edges[edgei].a = polypoints[edgei];
	edges[edgei].b = polypoints[(edgei + 1) % poly.pn];
    }
    if (pp->start.constrained) {
	evs[0].x = cos(pp->start.theta);
	evs[0].y = sin(pp->start.theta);
    } else
	evs[0].x = evs[0].y = 0;
    if (pp->end.constrained) {
	evs[1].x = -cos(pp->end.theta);
	evs[1].y = -sin(pp->end.theta);
    } else
	evs[1].x = evs[1].y = 0;

    if (Proutespline(edges, poly.pn, pl, evs, &spl) == -1)
	abort();
#ifdef DEBUG
    if (debugleveln(realedge, 3)) {
	psprintspline(spl);
	psprintinit(0);
    }
#endif
    mkspacep(spl.pn);
    for (bi = 0; bi <= boxn; bi++) {
	boxes[bi].LL.x = INT_MAX;
	boxes[bi].UR.x = INT_MIN;
    }
    for (splinepi = 0; splinepi < spl.pn; splinepi++) {
	ps[splinepi].x = spl.ps[splinepi].x;
	ps[splinepi].y = spl.ps[splinepi].y;
    }
    for (splinepi = 0; splinepi + 3 < spl.pn; splinepi += 3) {
	for (si = 0; si <= 10 * boxn; si++) {
	    t = si / (10.0 * boxn);
	    sp[0] = ps[splinepi];
	    sp[1] = ps[splinepi + 1];
	    sp[2] = ps[splinepi + 2];
	    sp[3] = ps[splinepi + 3];
	    sp[0].x = sp[0].x + t * (sp[1].x - sp[0].x);
	    sp[0].y = sp[0].y + t * (sp[1].y - sp[0].y);
	    sp[1].x = sp[1].x + t * (sp[2].x - sp[1].x);
	    sp[1].y = sp[1].y + t * (sp[2].y - sp[1].y);
	    sp[2].x = sp[2].x + t * (sp[3].x - sp[2].x);
	    sp[2].y = sp[2].y + t * (sp[3].y - sp[2].y);
	    sp[0].x = sp[0].x + t * (sp[1].x - sp[0].x);
	    sp[0].y = sp[0].y + t * (sp[1].y - sp[0].y);
	    sp[1].x = sp[1].x + t * (sp[2].x - sp[1].x);
	    sp[1].y = sp[1].y + t * (sp[2].y - sp[1].y);
	    sp[0].x = sp[0].x + t * (sp[1].x - sp[0].x);
	    sp[0].y = sp[0].y + t * (sp[1].y - sp[0].y);
	    for (bi = 0; bi < boxn; bi++) {
		if (sp[0].y <= boxes[bi].UR.y && sp[0].y >= boxes[bi].LL.y) {
		    if (boxes[bi].LL.x > sp[0].x)
			boxes[bi].LL.x = sp[0].x;
		    if (boxes[bi].UR.x < sp[0].x)
			boxes[bi].UR.x = sp[0].x;
		}
	    }
	}
    }
    *npoints = spl.pn;

#ifdef DEBUG
    if (GD_showboxes(realedge->head->graph) == 2 ||
	GD_showboxes(realedge->tail->graph) == 2 ||
	ED_showboxes(realedge) == 2 ||
	ND_showboxes(realedge->head) == 2 ||
	ND_showboxes(realedge->tail) == 2)
	printboxes(boxn, boxes);
#endif

    return ps;
}
Beispiel #2
0
/* append:
 */
static int 
append(path * path, int bi, point p0, point p1, int polysz)
{
    point v[8];		/* worst case 4 corners + 2 segs * 2 points each */
    point w[8];
    box b = path->boxes[bi];
    box bb;
    int i, i0, npw, delta;
    point q0 = { 0, 0 }, q1 = { 0, 0}, r;
    int pn;

    /* v = 4 corners of b, p0 and p1 */
    pn = 0;
    v[pn++] = b.LL;
    v[pn++] = mkpt(b.UR.x, b.LL.y);
    v[pn++] = b.UR;
    v[pn++] = mkpt(b.LL.x, b.UR.y);
    v[pn++] = p0;
    v[pn++] = p1;

    if (bi + 1 < path->nbox) {
	bb = path->boxes[bi + 1];
	/* determine points q0,q1 where b and bb touch and append to v */
	if (b.UR.x == bb.LL.x) {
	    q0.x = q1.x = b.UR.x;
	    q0.y = MIN(b.UR.y, bb.UR.y);
	    q1.y = MAX(b.LL.y, bb.LL.y);
	} else if (b.LL.x == bb.UR.x) {
	    q0.x = q1.x = b.LL.x;
	    q0.y = MIN(b.UR.y, bb.UR.y);
	    q1.y = MAX(b.LL.y, bb.LL.y);
	} else if (b.UR.y == bb.LL.y) {
	    q0.y = q1.y = b.UR.y;
	    q0.x = MIN(b.UR.x, bb.UR.x);
	    q1.x = MAX(b.LL.x, bb.LL.x);
	} else if (b.LL.y == bb.UR.y) {
	    q0.y = q1.y = b.LL.y;
	    q0.x = MIN(b.UR.x, bb.UR.x);
	    q1.x = MAX(b.LL.x, bb.LL.x);
	} else
	    abort();
	v[pn++] = q0;
	v[pn++] = q1;
    }

    /* sort v so that the cyclic order is p0, all other points, p1  */
    B = b;
    qsort(v, pn, sizeof(v[0]), cmpf);

    /* eliminate duplicates and record i0 = index of p0 in w */
    w[0] = v[0];
    npw = 1;
    i0 = -1;
    for (i = 0; i < pn; i++) {
	if (pteq(w[npw - 1], p0))
	    i0 = npw - 1;
	if (!pteq(v[i], w[npw - 1]))
	    w[npw++] = v[i];
    }

    i = i0;
    if (bi == 0)
	polysz = appendpt(p0, polysz);
    if (pteq(p1, w[(i0 + 1) % npw]))
	delta = -1;
    else if (pteq(p1, w[(i0 - 1 + npw) % npw]))
	delta = 1;
    else
	abort();
    do {
	i = (i + delta + npw) % npw;	/* go to the next point in order */
	r = w[i];		/* call it r */

	/* append r to current poly, except p0 and p1 are special cases */
	if ((bi == 0) || (!pteq(r, p0) && !pteq(r, p1)))
	    polysz = appendpt(r, polysz);
	if (pteq(r, p1))
	    break;
	if (bi + 1 < path->nbox) {	/* recur when we hit the next box */
	    if (pteq(r, q0)) {
		polysz = append(path, bi + 1, q0, q1, polysz);
		polysz = appendpt(q1, polysz);	/* assumes q1 != p0 and p1 */
		i += delta;	/* skip q1 */
	    } else if (pteq(r, q1)) {
		polysz = append(path, bi + 1, q1, q0, polysz);
		polysz = appendpt(q0, polysz);
		i += delta;
	    }
	}
    } while (i != i0);
    return polysz;
}
point *routesplines (path* pp, int* npoints)
{
    Ppoly_t poly;
    Ppolyline_t pl, spl;
    int splinepi;
    Ppoint_t eps[2];
    Pvector_t evs[2];
    int edgei, prev, next;
    point sp[4];
    int pi, bi, si;
    double t;

    nedges++;
    nboxes += pp->nbox;

    for (realedge = origedge = (edge_t *) pp->data;
            realedge && realedge->u.edge_type != NORMAL; realedge = realedge->u.to_orig)
        ;
    if (!realedge) {
        fprintf (stderr, "in routesplines, cannot find NORMAL edge\n");
        abort ();
    }
    thepath = pp;

    boxes = pp->boxes;
    boxn = pp->nbox;

    checkpath ();

    if (realedge->head->graph->u.showboxes == 1 ||
            realedge->tail->graph->u.showboxes == 1 ||
            realedge->u.showboxes == 1 ||
            realedge->head->u.showboxes == 1||
            realedge->tail->u.showboxes == 1)
        printpsboxes ();

    if (boxn * 8 > polypointn) {
        if (!polypoints) {
            if (!(polypoints = (Ppoint_t *)malloc (sizeof (Ppoint_t) * boxn * 8)))
                abort ();
        } else {
            if (!(polypoints = (Ppoint_t *)realloc (polypoints,
                    sizeof (Ppoint_t) * boxn * 8)))
                abort ();
        }
        polypointn = pp->nbox * 8;
    }

	if (realedge->tail != realedge->head) {
    /* I assume that the path goes either down only or
       up - right - down */
    for (bi = 0, pi = 0; bi < boxn; bi++) {
        next = prev = 0;
        if (bi > 0)
            prev = (boxes[bi].LL.y > boxes[bi - 1].LL.y) ? -1 : 1;
        if (bi < boxn - 1)
            next = (boxes[bi + 1].LL.y > boxes[bi].LL.y) ? 1 : -1;
        if (prev != next) {
            if (next == -1 || prev == 1) {
                polypoints[pi].x = boxes[bi].LL.x;
                polypoints[pi++].y = boxes[bi].UR.y;
                polypoints[pi].x = boxes[bi].LL.x;
                polypoints[pi++].y = boxes[bi].LL.y;
            } else {
                polypoints[pi].x = boxes[bi].UR.x;
                polypoints[pi++].y = boxes[bi].LL.y;
                polypoints[pi].x = boxes[bi].UR.x;
                polypoints[pi++].y = boxes[bi].UR.y;
            }
        } else {
            if (!(prev == -1 && next == -1))
                abort ();
        }
    }
    for (bi = boxn - 1; bi >= 0; bi--) {
        next = prev = 0;
        if (bi < boxn - 1)
            prev = (boxes[bi].LL.y > boxes[bi + 1].LL.y) ? -1 : 1;
        if (bi > 0)
            next = (boxes[bi - 1].LL.y > boxes[bi].LL.y) ? 1 : -1;
        if (prev != next) {
            if (next == -1 || prev == 1) {
                polypoints[pi].x = boxes[bi].LL.x;
                polypoints[pi++].y = boxes[bi].UR.y;
                polypoints[pi].x = boxes[bi].LL.x;
                polypoints[pi++].y = boxes[bi].LL.y;
            } else {
                polypoints[pi].x = boxes[bi].UR.x;
                polypoints[pi++].y = boxes[bi].LL.y;
                polypoints[pi].x = boxes[bi].UR.x;
                polypoints[pi++].y = boxes[bi].UR.y;
            }
        } else {
            if (!(prev == -1 && next == -1))
                abort ();
            polypoints[pi].x = boxes[bi].UR.x;
            polypoints[pi++].y = boxes[bi].LL.y;
            polypoints[pi].x = boxes[bi].UR.x;
            polypoints[pi++].y = boxes[bi].UR.y;
            polypoints[pi].x = boxes[bi].LL.x;
            polypoints[pi++].y = boxes[bi].UR.y;
            polypoints[pi].x = boxes[bi].LL.x;
            polypoints[pi++].y = boxes[bi].LL.y;
        }
    }
   } 
   else {
	   /* new, more generalized approach for self-edges.  We do not
	      assume any monotonicity about the box path, only that it
		  is simply connected.  We build up the constraint poly by
		  walking the box path from one end to the other and back
		  in the recursive function append(). A better approach to all
		  of this might be to dispense with the box paths altogether
		  and just compute the constraint poly directly, but this
		  needs to be done as part of a more thorough overhaul. */
		point p0, p1;
		box	b0,b1;
		b0 = pp->boxes[0]; b1 = pp->boxes[1];
		/* determine 'starting' segment (side of b0) for box path search */
		if      (b0.UR.x == b1.LL.x) {p0 = b0.LL; p1 = mkpt(b0.LL.x,b0.UR.y);}
		else if (b0.LL.y == b1.UR.y) {p0 = mkpt(b0.LL.x,b0.UR.y); p1 = b0.UR;}
		else if (b0.LL.x == b1.UR.x) {p0 = b0.UR; p1 = mkpt(b0.UR.x,b0.LL.y);}
		else if (b0.UR.y == b1.LL.y) {p0 = mkpt(b0.UR.x,b0.LL.y); p1 = b0.LL;}
		else abort();
		polysz = 0;
		append(pp,0,p0,p1);
		pi = polysz;
	}

    for (bi = 0; bi < boxn; bi++)
        boxes[bi].LL.x = INT_MAX, boxes[bi].UR.x = INT_MIN;
    poly.ps = polypoints, poly.pn = pi;
    eps[0].x = pp->start.p.x, eps[0].y = pp->start.p.y;
    eps[1].x = pp->end.p.x,   eps[1].y = pp->end.p.y;
    if (Pshortestpath (&poly, eps, &pl) == -1)
        abort ();
    if (poly.pn > edgen) {
        if (!edges) {
            if (!(edges = (Pedge_t *)malloc (sizeof (Pedge_t) * poly.pn)))
                abort ();
        } else {
            if (!(edges = (Pedge_t *)realloc (edges, sizeof (Pedge_t) * poly.pn)))
                abort ();
        }
        edgen = poly.pn;
    }
    for (edgei = 0; edgei < poly.pn; edgei++) {
        edges[edgei].a = polypoints[edgei];
        edges[edgei].b = polypoints[(edgei + 1) % poly.pn];
    }
    if (pp->start.constrained) {
        evs[0].x = cos (pp->start.theta);
        evs[0].y = sin (pp->start.theta);
    } else
        evs[0].x = evs[0].y = 0;
    if (pp->end.constrained) {
        evs[1].x = -cos (pp->end.theta);
        evs[1].y = -sin (pp->end.theta);
    } else
        evs[1].x = evs[1].y = 0;
    if (Proutespline (edges, poly.pn, pl, evs, &spl) == -1)
        abort ();
    mkspacep (spl.pn);
    for (bi = 0; bi <= boxn; bi++)
        boxes[bi].LL.x = minbbox.LL.x, boxes[bi].UR.x = minbbox.UR.x;
    for (splinepi = 0; splinepi < spl.pn; splinepi++) {
        ps[splinepi].x = (int)spl.ps[splinepi].x;
        ps[splinepi].y = (int)spl.ps[splinepi].y;
    }
    for (splinepi = 0; splinepi < spl.pn; splinepi += 3) {
        for (si = 0; si <= 10 * boxn; si++) {
            t = si / (10.0 * boxn);
            sp[0] = ps[splinepi];
            sp[1] = ps[splinepi + 1];
            sp[2] = ps[splinepi + 2];
            sp[3] = ps[splinepi + 3];
            sp[0].x = (int)(sp[0].x + t * (sp[1].x - sp[0].x));
            sp[0].y = (int)(sp[0].y + t * (sp[1].y - sp[0].y));
            sp[1].x = (int)(sp[1].x + t * (sp[2].x - sp[1].x));
            sp[1].y = (int)(sp[1].y + t * (sp[2].y - sp[1].y));
            sp[2].x = (int)(sp[2].x + t * (sp[3].x - sp[2].x));
            sp[2].y = (int)(sp[2].y + t * (sp[3].y - sp[2].y));
            sp[0].x = (int)(sp[0].x + t * (sp[1].x - sp[0].x));
            sp[0].y = (int)(sp[0].y + t * (sp[1].y - sp[0].y));
            sp[1].x = (int)(sp[1].x + t * (sp[2].x - sp[1].x));
            sp[1].y = (int)(sp[1].y + t * (sp[2].y - sp[1].y));
            sp[0].x = (int)(sp[0].x + t * (sp[1].x - sp[0].x));
            sp[0].y = (int)(sp[0].y + t * (sp[1].y - sp[0].y));
            for (bi = 0; bi < boxn; bi++) {
                if (sp[0].y <= boxes[bi].UR.y && sp[0].y >= boxes[bi].LL.y) {
                    if (boxes[bi].LL.x > sp[0].x)
                        boxes[bi].LL.x = sp[0].x;
                    if (boxes[bi].UR.x < sp[0].x)
                        boxes[bi].UR.x = sp[0].x;
                }
            }
        }
    }
    *npoints = spl.pn;

    if (realedge->head->graph->u.showboxes == 2 ||
            realedge->tail->graph->u.showboxes == 2 ||
            realedge->u.showboxes == 2 ||
            realedge->head->u.showboxes == 2||
            realedge->tail->u.showboxes == 2)
        printpsboxes ();

    return ps;
}