예제 #1
0
/* initItem:
 */
static void initItem(node_t * n, nitem * p, expand_t margin)
{
    int x = POINTS(SCALE * ND_pos(n)[0]);
    int y = POINTS(SCALE * ND_pos(n)[1]);
    int w2, h2;
    box b;

    if (margin.doAdd) {
	w2 = SCALE * (POINTS(ND_width(n)/2.0) + margin.x);
	h2 = SCALE * (POINTS(ND_height(n)/2.0) + margin.y);
    }
    else {
	w2 = POINTS(margin.x * SCALE2 * ND_width(n));
	h2 = POINTS(margin.y * SCALE2 * ND_height(n));
    }

    b.LL.x = x - w2;
    b.LL.y = y - h2;
    b.UR.x = x + w2;
    b.UR.y = y + h2;

    p->pos.x = x;
    p->pos.y = y;
    p->np = n;
    p->bb = b;
}
예제 #2
0
파일: tlayout.c 프로젝트: aosm/graphviz
/* applyAttr:
 * Attractive force = weight*(d*d)/K
 *  or        force = (d - L(e))*weight(e)
 */
static void
applyAttr (Agnode_t* p, Agnode_t* q, Agedge_t* e)
{
  double    xdelta, ydelta;
  double    force;
  double    dist;
  double    dist2;

  xdelta = ND_pos(q)[0] - ND_pos(p)[0];
  ydelta = ND_pos(q)[1] - ND_pos(p)[1];
  dist2 = xdelta*xdelta + ydelta*ydelta;
  while (dist2 == 0.0) {
    xdelta = 5 - rand()%10;
    ydelta = 5 - rand()%10;
    dist2 = xdelta*xdelta + ydelta*ydelta;
  }
  dist = sqrt (dist2);
  if (T_useNew)
   force = (ED_factor(e) * (dist - ED_dist(e)))/dist;
  else
    force = (ED_factor(e) * dist)/ED_dist(e);
  DISP(q)[0] -= xdelta * force;
  DISP(q)[1] -= ydelta * force;
  DISP(p)[0] += xdelta * force;
  DISP(p)[1] += ydelta * force;
}
예제 #3
0
point coord(node_t * n)
{
    pointf pf;
    pf.x = ND_pos(n)[0];
    pf.y = ND_pos(n)[1];
    return cvt2pt(pf);
}
예제 #4
0
파일: layout.c 프로젝트: zionyx/graphviz
/* evalPositions:
 * The input is laid out, but node coordinates
 * are relative to smallest containing cluster.
 * Walk through all nodes and clusters, translating
 * the positions to absolute coordinates.
 * Assume that when called, g's bounding box is
 * in absolute coordinates and that box of root graph
 * has LL at origin.
 */
static void evalPositions(graph_t * g, graph_t* rootg)
{
    int i;
    graph_t *subg;
    node_t *n;
    boxf bb;
    boxf sbb;

    bb = BB(g);

    /* translate nodes in g */
    if (g != rootg) {
	for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	    if (PARENT(n) != g)
		continue;
	    ND_pos(n)[0] += bb.LL.x;
	    ND_pos(n)[1] += bb.LL.y;
	}
    }

    /* translate top-level clusters and recurse */
    for (i = 1; i <= GD_n_cluster(g); i++) {
	subg = GD_clust(g)[i];
	if (g != rootg) {
	    sbb = BB(subg);
	    sbb.LL.x += bb.LL.x;
	    sbb.LL.y += bb.LL.y;
	    sbb.UR.x += bb.LL.x;
	    sbb.UR.y += bb.LL.y;
	    BB(subg) = sbb;
	}
	evalPositions(subg, rootg);
    }
}
예제 #5
0
 /* makeInfo:
  * For each node in the graph, create a Info data structure 
  */
static void makeInfo(Agraph_t * graph)
{
    Agnode_t *node;
    int i;
    Info_t *ip;

    nsites = agnnodes(graph);
    geominit();

    nodeInfo = N_GNEW(nsites, Info_t);

    node = agfstnode(graph);
    ip = nodeInfo;

    pmargin = expFactor (graph);
    for (i = 0; i < nsites; i++) {
	ip->site.coord.x = ND_pos(node)[0];
	ip->site.coord.y = ND_pos(node)[1];

	makePoly(&ip->poly, node, pmargin);

	ip->site.sitenbr = i;
	ip->site.refcnt = 1;
	ip->node = node;
	ip->verts = NULL;
	node = agnxtnode(graph, node);
	ip++;
    }
}
예제 #6
0
파일: utils.c 프로젝트: jho1965us/graphviz
pointf coord(node_t * n)
{
    pointf r;

    r.x = POINTS_PER_INCH * ND_pos(n)[0];
    r.y = POINTS_PER_INCH * ND_pos(n)[1];
    return r;
}
예제 #7
0
static void copyPos(Agraph_t * g)
{
    Agnode_t *n;
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	ND_coord_i(n).x = POINTS(ND_pos(n)[0]);
	ND_coord_i(n).y = POINTS(ND_pos(n)[1]);
    }
}
예제 #8
0
파일: tlayout.c 프로젝트: aosm/graphviz
/* applyRep:
 * Repulsive force = (K*K)/d
 *  or K*K/d*d
 */
static void
applyRep (Agnode_t* p, Agnode_t* q)
{
  double    xdelta, ydelta;

  xdelta = ND_pos(q)[0] - ND_pos(p)[0];
  ydelta = ND_pos(q)[1] - ND_pos(p)[1];
  doRep (p, q, xdelta, ydelta, xdelta*xdelta + ydelta*ydelta);
}
예제 #9
0
static void initPos(Agraph_t * g)
{
    Agnode_t *n;
    Agedge_t *e;
    double *pvec;
    char *p;
    point *sp;
    int pn;
    attrsym_t *N_pos = agfindnodeattr(g, "pos");
    attrsym_t *E_pos = agfindedgeattr(g, "pos");

    assert(N_pos);
    if (!E_pos) {
	if (doEdges)
	    fprintf(stderr, "Warning: turning off doEdges, graph %s\n",
		    g->name);
	doEdges = 0;
    }
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	pvec = ND_pos(n);
	p = agxget(n, N_pos->index);
	if (p[0] && (sscanf(p, "%lf,%lf", pvec, pvec + 1) == 2)) {
	    int i;
	    for (i = 0; i < NDIM; i++)
		pvec[i] = pvec[i] / PSinputscale;
	} else {
	    fprintf(stderr, "could not find pos for node %s in graph %s\n",
		    n->name, g->name);
	    exit(1);
	}
	ND_coord_i(n).x = POINTS(ND_pos(n)[0]);
	ND_coord_i(n).y = POINTS(ND_pos(n)[1]);
    }

    if (doEdges) {
	for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	    for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
		if ((sp = user_spline(E_pos, e, &pn)) != 0) {
		    clip_and_install(e, sp, pn);
		    free(sp);
		} else {
		    fprintf(stderr,
			    "Missing edge pos for edge %s - %s in graph %s\n",
			    n->name, e->head->name, g->name);
		    exit(1);
		}
	    }
	}
    }
}
예제 #10
0
static void
resetCoord (Agraph_t* g)
{
    node_t* np = agfstnode(g);
    double* sp = ND_pos(np);
    double* ps = sp;

    for (np = agfstnode(g); np; np = agnxtnode(g, np)) {
	ND_pos(np) = 0;
	ND_coord(np).x = INCH2PS(ps[0]);
	ND_coord(np).y = INCH2PS(ps[1]);
	ps += 2;
    }
    free (sp);
}
예제 #11
0
 /* makeInfo:
  * For each node in the graph, create a Info data structure 
  */
static int makeInfo(Agraph_t * graph)
{
    Agnode_t *node;
    int i;
    Info_t *ip;
    expand_t pmargin;
    int (*polyf)(Poly *, Agnode_t *, float, float);

    nsites = agnnodes(graph);
    geominit();

    nodeInfo = N_GNEW(nsites, Info_t);

    node = agfstnode(graph);
    ip = nodeInfo;

    pmargin = sepFactor (graph);

    if (pmargin.doAdd) {
	polyf = makeAddPoly;
	/* we need inches for makeAddPoly */
	pmargin.x = PS2INCH(pmargin.x);
	pmargin.y = PS2INCH(pmargin.y);
    }
	
    else polyf = makePoly;
    for (i = 0; i < nsites; i++) {
	ip->site.coord.x = ND_pos(node)[0];
	ip->site.coord.y = ND_pos(node)[1];

	if (polyf(&ip->poly, node, pmargin.x, pmargin.y)) {
	    free (nodeInfo);
	    nodeInfo = NULL;
	    return 1;
        }

	ip->site.sitenbr = i;
	ip->site.refcnt = 1;
	ip->node = node;
	ip->verts = NULL;
	node = agnxtnode(graph, node);
	ip++;
    }
    return 0;
}
예제 #12
0
파일: neatoinit.c 프로젝트: Chaduke/bah.mod
int user_pos(attrsym_t * posptr, attrsym_t * pinptr, node_t * np, int nG)
{
    double *pvec;
    char *p, c;
    double z;

    if (posptr == NULL)
	return FALSE;
    pvec = ND_pos(np);
    p = agxget(np, posptr->index);
    if (p[0]) {
	c = '\0';
	if ((Ndim >= 3) && 
            (sscanf(p, "%lf,%lf,%lf%c", pvec, pvec+1, pvec+2, &c) >= 3)){
	    ND_pinned(np) = P_SET;
	    if (PSinputscale > 0.0) {
		int i;
		for (i = 0; i < Ndim; i++)
		    pvec[i] = pvec[i] / PSinputscale;
	    }
	    if (Ndim > 3)
		jitter_d(np, nG, 3);
	    if ((c == '!')
		|| (pinptr && mapbool(agxget(np, pinptr->index))))
		ND_pinned(np) = P_PIN;
	    return TRUE;
	}
	else if (sscanf(p, "%lf,%lf%c", pvec, pvec + 1, &c) >= 2) {
	    ND_pinned(np) = P_SET;
	    if (PSinputscale > 0.0) {
		int i;
		for (i = 0; i < Ndim; i++)
		    pvec[i] = pvec[i] / PSinputscale;
	    }
	    if (Ndim > 2) {
		if (N_z && (p = agxget(np, N_z->index)) && 
                           (sscanf(p,"%lf",&z) == 1)) { 
		    if (PSinputscale > 0.0) {
			pvec[2] = z / PSinputscale;
		    }
		    else
			pvec[2] = z;
		    jitter_d(np, nG, 3);
		}
		else
		    jitter3d(np, nG);
	    }
	    if ((c == '!')
		|| (pinptr && mapbool(agxget(np, pinptr->index))))
		ND_pinned(np) = P_PIN;
	    return TRUE;
	} else
	    agerr(AGERR, "node %s, position %s, expected two doubles\n",
		  np->name, p);
    }
    return FALSE;
}
예제 #13
0
파일: neatoinit.c 프로젝트: Chaduke/bah.mod
void neato_cleanup_node(node_t * n)
{
    if (ND_shape(n)) {
	ND_shape(n)->fns->freefn(n);
    }
    free(ND_pos(n));
    free_label(ND_label(n));
    memset(&(n->u), 0, sizeof(Agnodeinfo_t));
}
예제 #14
0
/* initItem:
 */
static void initItem(node_t * n, nitem * p, double margin)
{
    int x = POINTS(SCALE * ND_pos(n)[0]);
    int y = POINTS(SCALE * ND_pos(n)[1]);
    int w2 = POINTS(margin * SCALE2 * ND_width(n));
    int h2 = POINTS(margin * SCALE2 * ND_height(n));
    box b;

    b.LL.x = x - w2;
    b.LL.y = y - h2;
    b.UR.x = x + w2;
    b.UR.y = y + h2;

    p->pos.x = x;
    p->pos.y = y;
    p->np = n;
    p->bb = b;
}
예제 #15
0
파일: tlayout.c 프로젝트: aosm/graphviz
/* fdp_tLayout:
 * Given graph g with ports nodes, layout g respecting ports.
 * If some node have position information, it may be useful to
 * reset temperature and other parameters to reflect this.
 */
void
fdp_tLayout (graph_t* g, xparams* xpms)
{
  int       i;
  int       reset;
  bport_t*  pp = PORTS(g);
  double    temp;
  Grid*     grid;
  pointf    ctr;
  Agnode_t* n;

  reset = init_params(g, xpms);
  temp = T0;

  ctr = initPositions (g, pp);
  
  if (T_useGrid) {
    grid = mkGrid (agnnodes (g));
    adjustGrid (grid, agnnodes (g));
    for (i = 0; i < loopcnt; i++) {
      temp = cool (temp, i);
      gAdjust (g, temp, pp, grid);
    }
    delGrid (grid);
  }
  else {
    for (i = 0; i < loopcnt; i++) {
      temp = cool (temp, i);
      adjust (g, temp, pp);
    }
  }

  if ((ctr.x != 0.0) || (ctr.y != 0.0)) {
    for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
      ND_pos(n)[0] += ctr.x;
      ND_pos(n)[1] += ctr.y;
    }
  }
dumpstat (g);
  if (reset) reset_params ();
}
예제 #16
0
static void dumpG(graph_t * g)
{
    node_t *n;
    /* point  p; */
    edge_t *e;

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	fprintf(stderr, " node %s \n", n->name);

	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    fprintf(stderr, " %s - %s \n", e->tail->name, e->head->name);
	}
#ifdef OLD
	p = coord(n);
	fprintf(stderr, " %s pos (%f,%f) (%d,%d)\n",
		n->name, ND_pos(n)[0], ND_pos(n)[1], p.x, p.y);
	fprintf(stderr, "   width %f height %f xsize %d ysize %d\n",
		ND_width(n), ND_height(n), ND_xsize(n), ND_ysize(n));
#endif
    }
}
예제 #17
0
파일: tlayout.c 프로젝트: aosm/graphviz
void
dumpstat (graph_t* g)
{
  double dx, dy;
  double l, max2 = 0.0;
  node_t* np;
  edge_t* ep;
  for (np = agfstnode(g); np; np = agnxtnode(g,np)) {
    dx = DISP(np)[0];
    dy = DISP(np)[1];
    l = dx*dx + dy*dy;
    if (l > max2) max2 = l;
    fprintf (stderr, "%s: (%f,%f) (%f,%f)\n", np->name,
      ND_pos(np)[0], ND_pos(np)[1],
      DISP(np)[0], DISP(np)[1]);
  }
  fprintf (stderr, "max delta = %f\n", sqrt(max2));
  for (np = agfstnode(g); np; np = agnxtnode(g,np)) {
    for (ep = agfstout(g,np); ep; ep = agnxtout(g,ep)) {
      dx = ND_pos(np)[0] - ND_pos(ep->head)[0];
      dy = ND_pos(np)[1] - ND_pos(ep->head)[1];
      fprintf (stderr, "  %s --  %s  (%f)\n", np->name, ep->head->name,
        sqrt(dx*dx + dy*dy));
    }
  }
}
예제 #18
0
/* applyDelta:
 * Recursively apply rotation rotate followed by translation (x,y)
 * to block sn and its children.
 */
static void applyDelta(block_t * sn, double x, double y, double rotate)
{
    block_t *child;
    Agraph_t *subg;
    Agnode_t *n;

    subg = sn->sub_graph;

    for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) {
	double X, Y;

	if (rotate != 0) {
	    double tmpX, tmpY;
	    double cosR, sinR;

	    tmpX = ND_pos(n)[0];
	    tmpY = ND_pos(n)[1];
	    cosR = cos(rotate);
	    sinR = sin(rotate);

	    X = tmpX * cosR - tmpY * sinR;
	    Y = tmpX * sinR + tmpY * cosR;
	} else {
	    X = ND_pos(n)[0];
	    Y = ND_pos(n)[1];
	}

	/* translate */
	ND_pos(n)[0] = X + x;
	ND_pos(n)[1] = Y + y;
    }

    for (child = sn->children.first; child; child = child->next)
	applyDelta(child, x, y, rotate);
}
예제 #19
0
/* circularLayout:
 * Do circular layout of g.
 * Assume g is strict.
 * g is a "connected" component of the derived graph of the
 * original graph.
 * We make state static so that it keeps a record of block numbers used
 * in a graph; it gets reset when a new root graph is used.
 */
void circularLayout(Agraph_t * g, Agraph_t* realg)
{
    block_t *root;
    static circ_state state;

    if (agnnodes(g) == 1) {
	Agnode_t *n = agfstnode(g);
	ND_pos(n)[0] = 0;
	ND_pos(n)[1] = 0;
	return;
    }

    initGraphAttrs(g, &state);

    if (mapbool(agget(realg, "oneblock")))
	root = createOneBlock(g, &state);
    else
	root = createBlocktree(g, &state);
    circPos(g, root, &state);

    cleanup(root, &state);
}
예제 #20
0
static pointf get_centroid(Agraph_t *g)
{
    int     cnt = 0;
    static pointf   sum = {0.0, 0.0};
    static Agraph_t *save;
    Agnode_t *n;

    sum.x = (GD_bb(g).LL.x + GD_bb(g).UR.x) / 2.0;
    sum.y = (GD_bb(g).LL.y + GD_bb(g).UR.y) / 2.0;
    return sum;

    if (save == g) return sum;
    save = g;
    for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
        sum.x += ND_pos(n)[0];
        sum.y += ND_pos(n)[1];
        cnt++;
    }
    sum.x = sum.x / cnt;
    sum.y = sum.y / cnt;
    return sum;
}
예제 #21
0
static void
attachPos (Agraph_t* g)
{
    node_t* np;
    double* ps = N_NEW(2*agnnodes(g), double);

    for (np = agfstnode(g); np; np = agnxtnode(g, np)) {
	ND_pos(np) = ps;
	ps[0] = PS2INCH(ND_coord(np).x);
	ps[1] = PS2INCH(ND_coord(np).y);
	ps += 2;
    }
}
예제 #22
0
파일: dbg.c 프로젝트: ekoontz/graphviz
/* dump:
 */
void dump(graph_t * g, int level, int doBB)
{
    node_t *n;
    boxf bb;
    double w, h;
    pointf pos;

    if (Verbose < level)
	return;
    prIndent();
    fprintf(stderr, "Graph %s : %d nodes\n", g->name, agnnodes(g));
    dumpBB(g);
    if (Verbose > level) {
	incInd();
	dumpSG(g);
	decInd();
	for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	    pos.x = ND_pos(n)[0];
	    pos.y = ND_pos(n)[1];
	    prIndent();
	    w = ND_width(n);
	    h = ND_height(n);
	    if (doBB) {
		bb.LL.x = pos.x - w / 2.0;
		bb.LL.y = pos.y - h / 2.0;
		bb.UR.x = bb.LL.x + w;
		bb.UR.y = bb.LL.y + h;
		fprintf(stderr, "%s: (%f,%f) ((%f,%f) , (%f,%f))\n",
			n->name, pos.x, pos.y, bb.LL.x, bb.LL.y, bb.UR.x,
			bb.UR.y);
	    } else {
		fprintf(stderr, "%s: (%f,%f) (%f,%f) \n",
			n->name, pos.x, pos.y, w, h);
	    }
	}
    }
}
예제 #23
0
static void scaleGraph (graph_t * g, node_t* root, pointf sc)
{
    pointf ctr;
    node_t* n;

    ctr.x = ND_pos(root)[0];
    ctr.y = ND_pos(root)[1];

    for (n = agfstnode(g); n; n = agnxtnode (g, n)) {
	if (n == root) continue;
	ND_pos(n)[0] = sc.x*(ND_pos(n)[0] - ctr.x) + ctr.x;
	ND_pos(n)[1] = sc.y*(ND_pos(n)[1] - ctr.y) + ctr.y;
    }
}
예제 #24
0
파일: sfdpinit.c 프로젝트: emdenrg/graphviz
/* getPos:
 */
static real *getPos(Agraph_t * g, spring_electrical_control ctrl)
{
    Agnode_t *n;
    real *pos = N_NEW(Ndim * agnnodes(g), real);
    int ix, i;

    if (agfindnodeattr(g, "pos") == NULL)
	return pos;

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	i = ND_id(n);
	if (hasPos(n)) {
	    for (ix = 0; ix < Ndim; ix++) {
		pos[i * Ndim + ix] = ND_pos(n)[ix];
	    }
	}
    }

    return pos;
}
예제 #25
0
/* initLayout:
 * Initialize node coordinates. If the node already has
 * a position, use it.
 * Return true if some node is fixed.
 */
int
initLayout(vtx_data * graph, int n, int dim, double **coords,
	   node_t ** nodes)
{
    node_t *np;
    double *xp;
    double *yp;
    double *pt;
    int i, d;
    int pinned = 0;

    xp = coords[0];
    yp = coords[1];
    for (i = 0; i < n; i++) {
	np = nodes[i];
	if (hasPos(np)) {
	    pt = ND_pos(np);
	    *xp++ = *pt++;
	    *yp++ = *pt++;
	    if (dim > 2) {
		for (d = 2; d < dim; d++)
		    coords[d][i] = *pt++;
	    }
	    if (isFixed(np))
		pinned = 1;
	} else {
	    *xp++ = drand48();
	    *yp++ = drand48();
	    if (dim > 2) {
		for (d = 2; d < dim; d++)
		    coords[d][i] = drand48();
	    }
	}
    }

    for (d = 0; d < dim; d++)
	orthog1(n, coords[d]);

    return pinned;
}
예제 #26
0
파일: fdpinit.c 프로젝트: ekoontz/graphviz
static void initialPositions(graph_t * g)
{
    int i;
    node_t *np;
    attrsym_t *possym;
    attrsym_t *pinsym;
    double *pvec;
    char *p;
    char c;

    possym = agfindattr(g->proto->n, "pos");
    if (!possym)
	return;
    pinsym = agfindattr(g->proto->n, "pin");
    for (i = 0; (np = GD_neato_nlist(g)[i]); i++) {
	p = agxget(np, possym->index);
	if (p[0]) {
	    pvec = ND_pos(np);
	    c = '\0';
	    if (sscanf(p, "%lf,%lf%c", pvec, pvec + 1, &c) >= 2) {
		if (PSinputscale > 0.0) {
		    int i;
		    for (i = 0; i < NDIM; i++)
			pvec[i] = pvec[i] / PSinputscale;
		}
		ND_pinned(np) = P_SET;
		if ((c == '!')
		    || (pinsym && mapbool(agxget(np, pinsym->index))))
		    ND_pinned(np) = P_PIN;
	    } else
		fprintf(stderr,
			"Warning: node %s, position %s, expected two floats\n",
			np->name, p);
	}
    }
}
예제 #27
0
파일: tlayout.c 프로젝트: aosm/graphviz
/* initPositions:
 * Create initial layout of nodes
 * TODO :
 *  Position nodes near neighbors with positions.
 *  Use bbox to reset K.
 */
static pointf
initPositions (graph_t* g, bport_t* pp)
{
  int       nG = agnnodes (g) - NPORTS (g);
  double    size;
  Agnode_t* np;
  int       n_pos = 0;  /* no. of nodes with position info */
  box       bb;
  pointf    ctr;        /* center of boundary ellipse */
  long      local_seed;
  double    PItimes2 = M_PI * 2.0;

  for (np = agfstnode(g); np; np = agnxtnode(g,np)) {
    if (ND_pinned(np)) {
      if (n_pos) {
        bb.LL.x = MIN(ND_pos(np)[0],bb.LL.x);
        bb.LL.y = MIN(ND_pos(np)[1],bb.LL.y);
        bb.UR.x = MAX(ND_pos(np)[0],bb.UR.x);
        bb.UR.y = MAX(ND_pos(np)[1],bb.UR.y);
      }
      else {
        bb.UR.x = bb.LL.x = ND_pos(np)[0];
        bb.UR.y = bb.LL.y = ND_pos(np)[1];
      }
      n_pos++;
    }
  }

  size = T_K * (sqrt((double)nG) + 1.0);
  Wd = Ht = expFactor*(size/2.0);
  if (n_pos == 1) {
    ctr.x = bb.LL.x;
    ctr.y = bb.LL.y;
  }
  else if (n_pos > 1) {
    double alpha, area, width, height, quot;
    ctr.x = (bb.LL.x + bb.UR.x)/2.0;
    ctr.y = (bb.LL.y + bb.UR.y)/2.0;
    width = expFactor*(bb.UR.x - bb.LL.x);
    height = expFactor*(bb.UR.y - bb.LL.y);
    area = 4.0*Wd*Ht;
    quot = (width*height)/area;
    if (quot >= 1.0) {   /* If bbox has large enough area, use it */
      Wd = width/2.0;
      Ht = height/2.0;
    }
    else if (quot > 0.0) {  /* else scale up to have enough area */
      quot = 2.0*sqrt(quot);
      Wd = width/quot;
      Ht = height/quot;
    }
    else {    /* either width or height is 0 */
      if (width > 0) {
        height = area/width;
        Wd = width/2.0;
        Ht = height/2.0;
      }
      else if (height > 0) {
        width = area/height;
        Wd = width/2.0;
        Ht = height/2.0;
      }
      /* If width = height = 0, use Wd and Ht as defined above for
       * the case the n_pos == 0.
       */
    }
    
      /* Construct enclosing ellipse */
    alpha = atan2 (Ht, Wd);
    Wd = Wd/cos(alpha);
    Ht = Ht/sin(alpha);
  }
  else {
    ctr.x = ctr.y = 0;
  }
  Wd2 = Wd*Wd;
  Ht2 = Ht*Ht;

    /* Set seed value */
  if (smode == seed_val) local_seed = T_seed;
  else {
#ifdef MSWIN32
    local_seed = time(NULL);
#else
    local_seed = getpid() ^ time(NULL);
#endif
  }
  srand48(local_seed);

  /* If ports, place ports on and nodes within an ellipse centered at origin
   * with halfwidth Wd and halfheight Ht. 
   * If no ports, place nodes within a rectangle centered at origin
   * with halfwidth Wd and halfheight Ht. Nodes with a given position
   * are translated. Wd and Ht are set to contain all positioned points.
   * The reverse translation will be applied to all
   * nodes at the end of the layout.
   * TODO: place unfixed points using adjacent ports or fixed pts.
   */
  if (pp) {
    while (pp->e) { /* position ports on ellipse */
      np = pp->n;
      ND_pos(np)[0] = Wd * cos(pp->alpha);
      ND_pos(np)[1] = Ht * sin(pp->alpha);
      ND_pinned(np) = P_SET;
      pp++;
    }
    for (np = agfstnode(g); np; np = agnxtnode(g,np)) {
      if (IS_PORT(np)) continue;
      if (ND_pinned(np)) {
        ND_pos(np)[0] -= ctr.x;
        ND_pos(np)[1] -= ctr.y;
      }
      else {
        double angle = PItimes2 * drand48();
        double radius = 0.9 * drand48();
        ND_pos(np)[0] = radius * Wd * cos(angle);
        ND_pos(np)[1] = radius * Ht * sin(angle);
      }
    }
  }
  else {
    if (n_pos) {  /* If positioned nodes */
      for (np = agfstnode(g); np; np = agnxtnode(g,np)) {
        if (ND_pinned(np)) {
          ND_pos(np)[0] -= ctr.x;
          ND_pos(np)[1] -= ctr.y;
        }
        else {
          ND_pos(np)[0] = Wd * (2.0*drand48() - 1.0);
          ND_pos(np)[1] = Ht * (2.0*drand48() - 1.0);
        }
      }
    }
    else {   /* No ports or positions; place randomly */
      for (np = agfstnode(g); np; np = agnxtnode(g,np)) {
        ND_pos(np)[0] = Wd * (2.0*drand48() - 1.0);
        ND_pos(np)[1] = Ht * (2.0*drand48() - 1.0);
      }
    }
  }

  return ctr;
}
예제 #28
0
/* scAdjust:
 * Scale the layout.
 * equal > 0  => scale uniformly in x and y to remove overlaps
 * equal = 0  => scale separately in x and y to remove overlaps
 * equal < 0  => scale down uniformly in x and y to remove excess space
 * The last assumes there are no overlaps at present.
 * Based on Marriott, Stuckey, Tam and He,
 * "Removing Node Overlapping in Graph Layout Using Constrained Optimization",
 * Constraints,8(2):143--172, 2003.
 */
int scAdjust(graph_t * g, int equal)
{
    int nnodes = agnnodes(g);
    info *nlist = N_GNEW(nnodes, info);
    info *p = nlist;
    node_t *n;
    pointf s;
    int i;
    expand_t margin;
    pointf *aarr;
    int m;

    margin = sepFactor (g);
    if (margin.doAdd) {
	/* we use inches below */
	margin.x = PS2INCH(margin.x);
	margin.y = PS2INCH(margin.y);
    }

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	double w2, h2;
	if (margin.doAdd) {
	    w2 = (ND_width(n) / 2.0) + margin.x;
	    h2 = (ND_height(n) / 2.0) + margin.y;
	}
	else {
	    w2 = margin.x * ND_width(n) / 2.0;
	    h2 = margin.y * ND_height(n) / 2.0;
	}
	p->pos.x = ND_pos(n)[0];
	p->pos.y = ND_pos(n)[1];
	p->bb.LL.x = p->pos.x - w2;
	p->bb.LL.y = p->pos.y - h2;
	p->bb.UR.x = p->pos.x + w2;
	p->bb.UR.y = p->pos.y + h2;
	p->wd2 = w2;
	p->ht2 = h2;
	p->np = n;
	p++;
    }

    if (equal < 0) {
	s.x = s.y = compress(nlist, nnodes);
	if (s.x == 0) {		/* overlaps exist */
	    free(nlist);
	    return 0;
	}
	fprintf(stderr, "compress %g \n", s.x);
    } else {
	aarr = mkOverlapSet(nlist, nnodes, &m);

	if (m == 0) {		/* no overlaps */
	    free(aarr);
	    free(nlist);
	    return 0;
	}

	if (equal) {
	    s.x = s.y = computeScale(aarr, m);
	} else {
	    s = computeScaleXY(aarr, m);
	}
	free(aarr);
    }

    p = nlist;
    for (i = 0; i < nnodes; i++) {
	ND_pos(p->np)[0] = s.x * p->pos.x;
	ND_pos(p->np)[1] = s.y * p->pos.y;
	p++;
    }

    free(nlist);
    return 1;
}
예제 #29
0
/* getRotation:
 * The function determines how much the block should be rotated
 * for best positioning with parent, assuming its center is at x and y
 * relative to the parent.
 * angle gives the angle of the new position, i.e., tan(angle) = y/x.
 * If sn has 2 nodes, we arrange the line of the 2 normal to angle.
 * If sn has 1 node, parent_pos has already been set to the 
 * correct angle assuming no rotation.
 * Otherwise, we find the node in sn connected to the parent and rotate
 * the block so that it is closer or at least visible to its node in the
 * parent.
 *
 * For COALESCED blocks, if neighbor is in left half plane, 
 * use unCOALESCED case.
 * Else let theta be angle, R = LEN(x,y), pho the radius of actual 
 * child block, phi be angle of neighbor in actual child block,
 * and r the distance from center of coalesced block to center of 
 * actual block. Then, the angle to rotate the coalesced block to
 * that the edge from the parent is tangent to the neighbor on the
 * actual child block circle is
 *    alpha = theta + M_PI/2 - phi - arcsin((l/R)*(sin B))
 * where l = r - rho/(cos phi) and beta = M_PI/2 + phi.
 * Thus, 
 *    alpha = theta + M_PI/2 - phi - arcsin((l/R)*(cos phi))
 */
static double
getRotation(block_t * sn, Agraph_t * g, double x, double y, double theta)
{
    double mindist2;
    Agraph_t *subg;
    /* Agedge_t* e; */
    Agnode_t *n, *closest_node, *neighbor;
    nodelist_t *list;
    double len2, newX, newY;
    int count;

    subg = sn->sub_graph;
#ifdef OLD
    parent = sn->parent;
#endif

    list = sn->circle_list;

    if (sn->parent_pos >= 0) {
	theta += M_PI - sn->parent_pos;
	if (theta < 0)
	    theta += 2 * M_PI;

	return theta;
    }

    count = sizeNodelist(list);
    if (count == 2) {
	return (theta - M_PI / 2.0);
    }

    /* Find node in block connected to block's parent */
    neighbor = CHILD(sn);
#ifdef OLD
    for (e = agfstedge(g, parent); e; e = agnxtedge(g, e, parent)) {
	n = e->head;
	if (n == parent)
	    n = e->tail;

	if ((BLOCK(n) == sn) && (PARENT(n) == parent)) {
	    neighbor = n;
	    break;
	}
    }
#endif
    newX = ND_pos(neighbor)[0] + x;
    newY = ND_pos(neighbor)[1] + y;
    mindist2 = LEN2(newX, newY);    /* save sqrts by using sqr of dist to find min */
    closest_node = neighbor;

    for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) {
	if (n == neighbor)
	    continue;

	newX = ND_pos(n)[0] + x;
	newY = ND_pos(n)[1] + y;

	len2 = LEN2(newX, newY);
	if (len2 < mindist2) {
	    mindist2 = len2;
	    closest_node = n;
	}
    }

    /* if((neighbor != closest_node) && !ISPARENT(neighbor)) { */
    if (neighbor != closest_node) {
	double rho = sn->rad0;
	double r = sn->radius - rho;
	double n_x = ND_pos(neighbor)[0];
	if (COALESCED(sn) && (-r < n_x)) {
	    double R = LEN(x, y);
	    double n_y = ND_pos(neighbor)[1];
	    double phi = atan2(n_y, n_x + r);
	    double l = r - rho / (cos(phi));

	    theta += M_PI / 2.0 - phi - asin((l / R) * (cos(phi)));
	} else {		/* Origin still at center of this block */
	    double phi = atan2(ND_pos(neighbor)[1], ND_pos(neighbor)[0]);
	    theta += M_PI - phi - PSI(neighbor);
	    if (theta > 2 * M_PI)
		theta -= 2 * M_PI;
	}
    } else
	theta = 0;
    return theta;
}
예제 #30
0
파일: tlayout.c 프로젝트: aosm/graphviz
static void
updatePos (Agraph_t* g, double temp, bport_t* pp)
{
  Agnode_t*    n;
  double       temp2;
  double       len2;
  double       x,y,d;
  double       dx,dy;

  temp2 = temp * temp;
  for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
    if (ND_pinned(n) & P_FIX) continue;
    dx = DISP(n)[0];
    dy = DISP(n)[1];
    len2 = dx*dx + dy*dy;

      /* limit by temperature */
    if (len2 < temp2) {
      x = ND_pos(n)[0] + dx;
      y = ND_pos(n)[1] + dy;
    }
    else {
      double fact = temp/(sqrt(len2));
      x = ND_pos(n)[0] + dx*fact;
      y = ND_pos(n)[1] + dy*fact;
    }
    
      /* if ports, limit by boundary */
    if (pp) {
      d = sqrt((x*x)/Wd2 + (y*y)/Ht2);
      if (IS_PORT(n)) {
        ND_pos(n)[0] = x/d;
        ND_pos(n)[1] = y/d;
      }
      else if (d >= 1.0) {
        ND_pos(n)[0] = 0.95*x/d;
        ND_pos(n)[1] = 0.95*y/d;
      }
      else {
        ND_pos(n)[0] = x;
        ND_pos(n)[1] = y;
      }
    }
    else {
      ND_pos(n)[0] = x;
      ND_pos(n)[1] = y;
    }
  }
}