/* 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; }
/* _spline_edges: * Basic default routine for creating edges. * If splines are requested, we construct the obstacles. * If not, or nodes overlap, the function reverts to line segments. * NOTE: intra-cluster edges are not constrained to * remain in the cluster's bounding box and, conversely, a cluster's box * is not altered to reflect intra-cluster edges. * If Nop > 1 and the spline exists, it is just copied. * NOTE: if edgetype = ET_NONE, we shouldn't be here. */ static int _spline_edges(graph_t * g, expand_t* pmargin, int edgetype) { node_t *n; edge_t *e; edge_t *e0; Ppoly_t **obs = 0; Ppoly_t *obp; int cnt, i = 0, npoly; vconfig_t *vconfig = 0; path *P = NULL; int useEdges = (Nop > 1); router_t* rtr = 0; int legal = 0; /* build configuration */ if (edgetype >= ET_PLINE) { obs = N_NEW(agnnodes(g), Ppoly_t *); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { obp = makeObstacle(n, pmargin, edgetype == ET_ORTHO); if (obp) { ND_lim(n) = i; obs[i++] = obp; } else ND_lim(n) = POLYID_NONE; } } else {
/* 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); } }