/* getPath * Construct the shortest path from one endpoint of e to the other. * The obstacles and their number are given by obs and npoly. * vconfig is a precomputed data structure to help in the computation. * If chkPts is true, the function finds the polygons, if any, containing * the endpoints and tells the shortest path computation to ignore them. * Assumes this info is set in ND_lim, usually from _spline_edges. * Returns the shortest path. */ Ppolyline_t getPath(edge_t * e, vconfig_t * vconfig, int chkPts, Ppoly_t ** obs, int npoly) { Ppolyline_t line; int pp, qp; Ppoint_t p, q; p = add_pointf(ND_coord(agtail(e)), ED_tail_port(e).p); q = add_pointf(ND_coord(aghead(e)), ED_head_port(e).p); /* determine the polygons (if any) that contain the endpoints */ pp = qp = POLYID_NONE; if (chkPts) { pp = ND_lim(agtail(e)); qp = ND_lim(aghead(e)); /* for (i = 0; i < npoly; i++) { if ((pp == POLYID_NONE) && in_poly(*obs[i], p)) pp = i; if ((qp == POLYID_NONE) && in_poly(*obs[i], q)) qp = i; } */ } Pobspath(vconfig, p, pp, q, qp, &line); return line; }
/* makeStraightEdge: * * FIX: handle ports on boundary? */ void makeStraightEdge(graph_t * g, edge_t * e, int et, splineInfo* sinfo) { pointf dumb[4]; node_t *n = agtail(e); node_t *head = aghead(e); int e_cnt = ED_count(e); int curved = (et == ET_CURVED); pointf perp; pointf del; edge_t *e0; int i, j, xstep, dx; double l_perp; pointf dumber[4]; pointf p, q; p = dumb[1] = dumb[0] = add_pointf(ND_coord(n), ED_tail_port(e).p); q = dumb[2] = dumb[3] = add_pointf(ND_coord(head), ED_head_port(e).p); if ((e_cnt == 1) || Concentrate) { if (curved) bend(dumb,get_centroid(g)); clip_and_install(e, aghead(e), dumb, 4, sinfo); addEdgeLabels(g, e, p, q); return; } e0 = e; if (APPROXEQPT(dumb[0], dumb[3], MILLIPOINT)) { /* degenerate case */ dumb[1] = dumb[0]; dumb[2] = dumb[3]; del.x = 0; del.y = 0; } else { perp.x = dumb[0].y - dumb[3].y; perp.y = dumb[3].x - dumb[0].x; l_perp = LEN(perp.x, perp.y); xstep = GD_nodesep(g->root); dx = xstep * (e_cnt - 1) / 2; dumb[1].x = dumb[0].x + (dx * perp.x) / l_perp; dumb[1].y = dumb[0].y + (dx * perp.y) / l_perp; dumb[2].x = dumb[3].x + (dx * perp.x) / l_perp; dumb[2].y = dumb[3].y + (dx * perp.y) / l_perp; del.x = -xstep * perp.x / l_perp; del.y = -xstep * perp.y / l_perp; } for (i = 0; i < e_cnt; i++) { if (aghead(e0) == head) { p = dumb[0]; q = dumb[3]; for (j = 0; j < 4; j++) { dumber[j] = dumb[j]; } } else { p = dumb[3]; q = dumb[0]; for (j = 0; j < 4; j++) { dumber[3 - j] = dumb[j]; } } if (et == ET_PLINE) { Ppoint_t pts[4]; Ppolyline_t spl, line; line.pn = 4; line.ps = pts; for (j=0; j < 4; j++) { pts[j] = dumber[j]; } make_polyline (line, &spl); clip_and_install(e0, aghead(e0), spl.ps, spl.pn, sinfo); } else clip_and_install(e0, aghead(e0), dumber, 4, sinfo); addEdgeLabels(g, e0, p, q); e0 = ED_to_virt(e0); dumb[1].x += del.x; dumb[1].y += del.y; dumb[2].x += del.x; dumb[2].y += del.y; } }
/* compute_bb: * Compute bounding box of g using nodes, splines, and clusters. * Assumes bb of clusters already computed. * store in GD_bb. */ void compute_bb(graph_t * g) { node_t *n; edge_t *e; boxf b, bb; boxf BF; pointf ptf, s2; int i, j; if ((agnnodes(g) == 0) && (GD_n_cluster(g) ==0)) { bb.LL = pointfof(0, 0); bb.UR = pointfof(0, 0); return; } bb.LL = pointfof(INT_MAX, INT_MAX); bb.UR = pointfof(-INT_MAX, -INT_MAX); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { ptf = coord(n); s2.x = ND_xsize(n) / 2.0; s2.y = ND_ysize(n) / 2.0; b.LL = sub_pointf(ptf, s2); b.UR = add_pointf(ptf, s2); EXPANDBB(bb,b); if (ND_xlabel(n) && ND_xlabel(n)->set) { bb = addLabelBB(bb, ND_xlabel(n), GD_flip(g)); } for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (ED_spl(e) == 0) continue; for (i = 0; i < ED_spl(e)->size; i++) { for (j = 0; j < (((Agedgeinfo_t*)AGDATA(e))->spl)->list[i].size; j++) { ptf = ED_spl(e)->list[i].list[j]; EXPANDBP(bb,ptf); } } if (ED_label(e) && ED_label(e)->set) { bb = addLabelBB(bb, ED_label(e), GD_flip(g)); } if (ED_head_label(e) && ED_head_label(e)->set) { bb = addLabelBB(bb, ED_head_label(e), GD_flip(g)); } if (ED_tail_label(e) && ED_tail_label(e)->set) { bb = addLabelBB(bb, ED_tail_label(e), GD_flip(g)); } if (ED_xlabel(e) && ED_xlabel(e)->set) { bb = addLabelBB(bb, ED_xlabel(e), GD_flip(g)); } } } for (i = 1; i <= GD_n_cluster(g); i++) { B2BF(GD_bb(GD_clust(g)[i]), BF); EXPANDBB(bb,BF); } if (GD_label(g) && GD_label(g)->set) { bb = addLabelBB(bb, GD_label(g), GD_flip(g)); } GD_bb(g) = bb; }
/* addEndpoint: * Add node to graph representing spline end point p inside obstruction obs_id. * For each side of obstruction, add edge from p to corresponding triangle. * The node id of the new node in the graph is v_id. * If p lies on the side of its node (sides != 0), we limit the triangles * to those within 45 degrees of each side of the natural direction of p. */ static void addEndpoint(router_t * rtr, pointf p, node_t* v, int v_id, int sides) { int obs_id = ND_lim(v); int starti = rtr->obs[obs_id]; int endi = rtr->obs[obs_id + 1]; pointf* pts = rtr->ps; int i, t; double d; pointf vr, v0, v1; switch (sides) { case TOP : vr = add_pointf (p, north); v0 = add_pointf (p, northwest); v1 = add_pointf (p, northeast); break; case TOP|RIGHT : vr = add_pointf (p, northeast); v0 = add_pointf (p, north); v1 = add_pointf (p, east); break; case RIGHT : vr = add_pointf (p, east); v0 = add_pointf (p, northeast); v1 = add_pointf (p, southeast); break; case BOTTOM|RIGHT : vr = add_pointf (p, southeast); v0 = add_pointf (p, east); v1 = add_pointf (p, south); break; case BOTTOM : vr = add_pointf (p, south); v0 = add_pointf (p, southeast); v1 = add_pointf (p, southwest); break; case BOTTOM|LEFT : vr = add_pointf (p, southwest); v0 = add_pointf (p, south); v1 = add_pointf (p, west); break; case LEFT : vr = add_pointf (p, west); v0 = add_pointf (p, southwest); v1 = add_pointf (p, northwest); break; case TOP|LEFT : vr = add_pointf (p, northwest); v0 = add_pointf (p, west); v1 = add_pointf (p, north); break; case 0 : break; default : assert (0); break; } rtr->tg->nodes[v_id].ne = 0; rtr->tg->nodes[v_id].ctr = p; for (i = starti; i < endi; i++) { ipair seg; seg.i = i; if (i < endi - 1) seg.j = i + 1; else seg.j = starti; t = findMap(rtr->trimap, seg.i, seg.j); if (sides && !inCone (v0, p, v1, pts[seg.i]) && !inCone (v0, p, v1, pts[seg.j]) && !raySeg(p,vr,pts[seg.i],pts[seg.j])) continue; d = DIST(p, (rtr->tg->nodes + t)->ctr); addTriEdge(rtr->tg, v_id, t, d, seg); } }