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]); } }
static pointf vrml_node_point(GVJ_t *job, node_t *n, pointf p) { pointf rv; /* make rv relative to PNG canvas */ if (job->rotation) { rv.x = ( (p.y - job->pad.y) - ND_coord_i(n).y + ND_lw_i(n) ) * Scale + NODE_PAD; rv.y = (-(p.x - job->pad.x) + ND_coord_i(n).x + ND_ht_i(n) / 2.) * Scale + NODE_PAD; } else { rv.x = ( (p.x - job->pad.x) - ND_coord_i(n).x + ND_lw_i(n) ) * Scale + NODE_PAD; rv.y = (-(p.y - job->pad.y) + ND_coord_i(n).y + ND_ht_i(n) / 2.) * Scale + NODE_PAD; } return rv; }
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); } } } } }
static void set_record_rects(node_t * n, field_t * f, agxbuf * xb) { int i; char buf[BUFSIZ]; if (f->n_flds == 0) { sprintf(buf, "%d,%d,%d,%d ", f->b.LL.x + ND_coord_i(n).x, YDIR(f->b.LL.y + ND_coord_i(n).y), f->b.UR.x + ND_coord_i(n).x, YDIR(f->b.UR.y + ND_coord_i(n).y)); agxbput(xb, buf); } for (i = 0; i < f->n_flds; i++) set_record_rects(n, f->fld[i], xb); }
static void vrml_bezier(GVJ_t *job, pointf * A, int n, int arrow_at_start, int arrow_at_end, int filled) { FILE *out = job->output_file; obj_state_t *obj = job->obj; edge_t *e = obj->u.e; double fstz = obj->tail_z, sndz = obj->head_z; pointf p1, V[4]; int i, j, step; assert(e); if (straight(A,n)) { doSegment (job, A, ND_coord_i(e->tail),Fstz,ND_coord_i(e->head),Sndz); return; } fprintf(out, "Shape { geometry Extrusion {\n"); fprintf(out, " spine ["); V[3] = A[0]; for (i = 0; i + 3 < n; i += 3) { V[0] = V[3]; for (j = 1; j <= 3; j++) V[j] = A[i + j]; for (step = 0; step <= BEZIERSUBDIVISION; step++) { p1 = Bezier(V, 3, (double) step / BEZIERSUBDIVISION, NULL, NULL); fprintf(out, " %.3f %.3f %.3f", p1.x, p1.y, interpolate_zcoord(job, p1, A[0], fstz, A[n - 1], sndz)); } } fprintf(out, " ]\n"); fprintf(out, " crossSection [ %.3f %.3f, %.3f %.3f, %.3f %.3f, %.3f %.3f ]\n", (obj->penwidth), (obj->penwidth), -(obj->penwidth), (obj->penwidth), -(obj->penwidth), -(obj->penwidth), (obj->penwidth), -(obj->penwidth)); fprintf(out, "}\n"); fprintf(out, " appearance DEF E%d Appearance {\n", e->id); fprintf(out, " material Material {\n"); fprintf(out, " ambientIntensity 0.33\n"); fprintf(out, " diffuseColor %.3f %.3f %.3f\n", obj->pencolor.u.rgba[0] / 255., obj->pencolor.u.rgba[1] / 255., obj->pencolor.u.rgba[2] / 255.); fprintf(out, " }\n"); fprintf(out, " }\n"); fprintf(out, "}\n"); }
/* doArrowhead: * If edge is straight, we attach a cone to the edge as a group. */ static void doArrowhead (GVJ_t *job, pointf * A) { FILE *out = job->output_file; obj_state_t *obj = job->obj; edge_t *e = obj->u.e; double rad, ht, y; pointf p0; /* center of triangle base */ point tp,hp; p0.x = (A[0].x + A[2].x)/2.0; p0.y = (A[0].y + A[2].y)/2.0; rad = DIST(A[0],A[2])/2.0; ht = DIST(p0,A[1]); y = (CylHt + ht)/2.0; tp = ND_coord_i(e->tail); hp = ND_coord_i(e->head); fprintf(out, "Transform {\n"); if (DIST2(A[1], tp) < DIST2(A[1], hp)) { TailHt = ht; fprintf(out, " translation 0 %.3f 0\n", -y); fprintf(out, " rotation 0 0 1 %.3f\n", M_PI); } else { HeadHt = ht; fprintf(out, " translation 0 %.3f 0\n", y); } fprintf(out, " children [\n"); fprintf(out, " Shape {\n"); fprintf(out, " geometry Cone {bottomRadius %.3f height %.3f }\n", rad, ht); fprintf(out, " appearance Appearance {\n"); fprintf(out, " material Material {\n"); fprintf(out, " ambientIntensity 0.33\n"); fprintf(out, " diffuseColor %.3f %.3f %.3f\n", obj->pencolor.u.rgba[0] / 255., obj->pencolor.u.rgba[1] / 255., obj->pencolor.u.rgba[2] / 255.); fprintf(out, " }\n"); fprintf(out, " }\n"); fprintf(out, " }\n"); fprintf(out, " ]\n"); fprintf(out, "}\n"); }
/* html_path: * Return a box in a table containing the given endpoint. * If the top flow is text (no internal structure), return * the box of the flow * Else return the box of the subtable containing the point. * Because of spacing, the point might not be in any subtable. * In that case, return the top flow's box. * Note that box[0] must contain the edge point. Additional boxes * move out to the boundary. * * At present, unimplemented, since the label may be inside a * non-box node and we need to figure out what this means. */ int html_path(node_t * n, port* p, int side, box * rv, int *k) { #ifdef UNIMPL point p; tbl_t *info; tbl_t *t; box b; int i; info = (tbl_t *) ND_shape_info(n); assert(info->tbls); info = info->tbls[0]; /* top-level flow */ assert(IS_FLOW(info)); b = info->box; if (info->tbl) { info = info->tbl; if (pt == 1) p = ED_tail_port(e).p; else p = ED_head_port(e).p; p = flip_pt(p, GD_rankdir(n->graph)); /* move p to node's coordinate system */ for (i = 0; (t = info->tbls[i]) != 0; i++) if (INSIDE(p, t->box)) { b = t->box; break; } } /* move box into layout coordinate system */ if (GD_flip(n->graph)) b = flip_trans_box(b, ND_coord_i(n)); else b = move_box(b, ND_coord_i(n)); *k = 1; *rv = b; if (pt == 1) return BOTTOM; else return TOP; #endif return 0; }
/* translate_drawing: * Translate and/or rotate nodes, spline points, and bbox info if * Offset is non-trivial. * Also, if Rankdir, reset ND_lw, ND_rw, and ND_ht to correct value. */ static void translate_drawing(graph_t * g) { node_t *v; edge_t *e; int shift = (Offset.x || Offset.y); if (!shift && !Rankdir) return; for (v = agfstnode(g); v; v = agnxtnode(g, v)) { if (Rankdir) dot_nodesize(v, FALSE); if (shift) { ND_coord_i(v) = map_point(ND_coord_i(v)); if (State == GVSPLINES) for (e = agfstout(g, v); e; e = agnxtout(g, e)) map_edge(e); } } if (shift) translate_bb(g, GD_rankdir(g)); }
static void finishSegment (FILE *out, edge_t *e) { point p0 = ND_coord_i(e->tail); point p1 = ND_coord_i(e->head); double o_x, o_y, o_z; double x, y, y0, z, theta; o_x = ((double)(p0.x + p1.x))/2; o_y = ((double)(p0.y + p1.y))/2; o_z = (Fstz + Sndz)/2; /* Compute rotation */ /* Pick end point with highest y */ if (p0.y > p1.y) { x = p0.x; y = p0.y; z = Fstz; } else { x = p1.x; y = p1.y; z = Sndz; } /* Translate center to the origin */ x -= o_x; y -= o_y; z -= o_z; if (p0.y > p1.y) theta = acos(2*y/EdgeLen) + M_PI; else theta = acos(2*y/EdgeLen); if (!x && !z) /* parallel to y-axis */ x = 1; y0 = (HeadHt-TailHt)/2.0; fprintf(out, " ]\n"); fprintf(out, " center 0 %.3f 0\n", y0); fprintf(out, " rotation %.3f 0 %.3f %.3f\n", -z, x, -theta); fprintf(out, " translation %.3f %.3f %.3f\n", o_x, o_y - y0, o_z); fprintf(out, " }\n"); }
/* Ensures that a new canvas item is created for this node and moved to right * position, or just moves an existing canvas item if already created. */ static void cls_node_ensure_draw (gpointer klass_id, ClsNode *cls_node, ClsBox *bounding_box) { gdouble x, y; point node_pos; #ifndef ND_coord_i pointf node_posf; #endif /* get some infos from the node */ #ifdef ND_coord_i node_pos = ND_coord_i (cls_node->agnode); #else node_posf = ND_coord (cls_node->agnode); PF2P (node_posf, node_pos); #endif /* Determine node coords and size *in* canvas world coordinate system */ cls_node->width = INCH_TO_PIXELS (ND_width (cls_node->agnode)); cls_node->height = INCH_TO_PIXELS (ND_height (cls_node->agnode)); cls_node->x1 = node_pos.x - cls_node->width/2; cls_node->y1 = GRAPH_TO_CANVAS_Y ((node_pos.y + cls_node->height/2)); cls_node->x2 = node_pos.x + cls_node->width/2; cls_node->y2 = GRAPH_TO_CANVAS_Y ((node_pos.y - cls_node->height/2)); if (cls_node->x1 < bounding_box->x1) bounding_box->x1 = cls_node->x1; if (cls_node->y1 < bounding_box->y1) bounding_box->y1 = cls_node->y1; if (cls_node->x2 > bounding_box->x2) bounding_box->x2 = cls_node->x2; if (cls_node->y2 > bounding_box->y2) bounding_box->y2 = cls_node->y2; if (cls_node->canvas_group == NULL || cls_node->drawn_expansion_status != cls_node->expansion_status) { if (cls_node->expansion_status == CLS_NODE_COLLAPSED) cls_node_draw_collapsed (cls_node); else cls_node_draw_expanded (cls_node); } /* Move the canvas item to right place */ x = cls_node->x1; y = cls_node->y1; foo_canvas_item_set (cls_node->canvas_group, "x", x, "y", y, NULL); g_hash_table_foreach (cls_node->edges_to, (GHFunc) cls_node_draw_edge, cls_node); }
/* _write_plain: */ void write_plain(GVJ_t * job, graph_t * g, FILE * f, bool extend) { int i, j, splinePoints; char *tport, *hport; node_t *n; edge_t *e; bezier bz; point pt; char *lbl; // setup_graph(job, g); setYInvert(g); pt = GD_bb(g).UR; fprintf(f, "graph %.3f %.3f %.3f\n", job->zoom, PS2INCH(pt.x), PS2INCH(pt.y)); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (IS_CLUST_NODE(n)) continue; fprintf(f, "node %s ", agcanonical(n->name)); printptf(f, ND_coord_i(n)); if (ND_label(n)->html) /* if html, get original text */ lbl = agxget(n, N_label->index); else lbl = ND_label(n)->text; if (lbl) lbl = agcanonical(lbl); else lbl = "\"\""; fprintf(f, " %.3f %.3f %s %s %s %s %s\n", ND_width(n), ND_height(n), lbl, late_nnstring(n, N_style, "solid"), ND_shape(n)->name, late_nnstring(n, N_color, DEFAULT_COLOR), late_nnstring(n, N_fillcolor, DEFAULT_FILL)); } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (extend && e->attr) { tport = e->attr[TAILX]; hport = e->attr[HEADX]; } else tport = hport = ""; if (ED_spl(e)) { splinePoints = 0; for (i = 0; i < ED_spl(e)->size; i++) { bz = ED_spl(e)->list[i]; splinePoints += bz.size; } fprintf(f, "edge "); writenodeandport(f, e->tail, tport); fprintf(f, " "); writenodeandport(f, e->head, hport); fprintf(f, " %d", splinePoints); for (i = 0; i < ED_spl(e)->size; i++) { bz = ED_spl(e)->list[i]; for (j = 0; j < bz.size; j++) printptf(f, bz.list[j]); } } if (ED_label(e)) { fprintf(f, " %s", agcanonical(ED_label(e)->text)); printptf(f, ED_label(e)->p); } fprintf(f, " %s %s\n", late_nnstring(e, E_style, "solid"), late_nnstring(e, E_color, DEFAULT_COLOR)); } } fprintf(f, "stop\n"); }
void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep) { int e_arrows; /* graph has edges with end arrows */ int s_arrows; /* graph has edges with start arrows */ int i, j, sides; char buf[BUFSIZ]; /* Used only for small strings */ unsigned char xbuffer[BUFSIZ]; /* Initial buffer for xb */ agxbuf xb; node_t *n; edge_t *e; point pt; e_arrows = s_arrows = 0; setYInvert(g); agxbinit(&xb, BUFSIZ, xbuffer); safe_dcl(g, g->proto->n, "pos", "", agnodeattr); safe_dcl(g, g->proto->n, "rects", "", agnodeattr); N_width = safe_dcl(g, g->proto->n, "width", "", agnodeattr); N_height = safe_dcl(g, g->proto->n, "height", "", agnodeattr); safe_dcl(g, g->proto->e, "pos", "", agedgeattr); if (GD_has_labels(g) & EDGE_LABEL) safe_dcl(g, g->proto->e, "lp", "", agedgeattr); if (GD_has_labels(g) & HEAD_LABEL) safe_dcl(g, g->proto->e, "head_lp", "", agedgeattr); if (GD_has_labels(g) & TAIL_LABEL) safe_dcl(g, g->proto->e, "tail_lp", "", agedgeattr); if (GD_label(g)) { safe_dcl(g, g, "lp", "", agraphattr); if (GD_label(g)->text[0]) { pt = GD_label(g)->p; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agset(g, "lp", buf); } } safe_dcl(g, g, "bb", "", agraphattr); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { sprintf(buf, "%d,%d", ND_coord_i(n).x, YDIR(ND_coord_i(n).y)); agset(n, "pos", buf); sprintf(buf, "%.2f", PS2INCH(ND_ht_i(n))); agxset(n, N_height->index, buf); sprintf(buf, "%.2f", PS2INCH(ND_lw_i(n) + ND_rw_i(n))); agxset(n, N_width->index, buf); if (strcmp(ND_shape(n)->name, "record") == 0) { set_record_rects(n, ND_shape_info(n), &xb); agxbpop(&xb); /* get rid of last space */ agset(n, "rects", agxbuse(&xb)); } else { polygon_t *poly; int i; if (N_vertices && isPolygon(n)) { poly = (polygon_t *) ND_shape_info(n); sides = poly->sides; if (sides < 3) { char *p = agget(n, "samplepoints"); if (p) sides = atoi(p); else sides = 8; if (sides < 3) sides = 8; } for (i = 0; i < sides; i++) { if (i > 0) agxbputc(&xb, ' '); if (poly->sides >= 3) sprintf(buf, "%.3f %.3f", PS2INCH(poly->vertices[i].x), YFDIR(PS2INCH(poly->vertices[i].y))); else sprintf(buf, "%.3f %.3f", ND_width(n) / 2.0 * cos(i / (double) sides * PI * 2.0), YFDIR(ND_height(n) / 2.0 * sin(i / (double) sides * PI * 2.0))); agxbput(&xb, buf); } agxset(n, N_vertices->index, agxbuse(&xb)); } } if (State >= GVSPLINES) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (ED_edge_type(e) == IGNORED) continue; if (ED_spl(e) == NULL) continue; /* reported in postproc */ for (i = 0; i < ED_spl(e)->size; i++) { if (i > 0) agxbputc(&xb, ';'); if (ED_spl(e)->list[i].sflag) { s_arrows = 1; sprintf(buf, "s,%d,%d ", ED_spl(e)->list[i].sp.x, YDIR(ED_spl(e)->list[i].sp.y)); agxbput(&xb, buf); } if (ED_spl(e)->list[i].eflag) { e_arrows = 1; sprintf(buf, "e,%d,%d ", ED_spl(e)->list[i].ep.x, YDIR(ED_spl(e)->list[i].ep.y)); agxbput(&xb, buf); } for (j = 0; j < ED_spl(e)->list[i].size; j++) { if (j > 0) agxbputc(&xb, ' '); pt = ED_spl(e)->list[i].list[j]; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agxbput(&xb, buf); } } agset(e, "pos", agxbuse(&xb)); if (ED_label(e)) { pt = ED_label(e)->p; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agset(e, "lp", buf); } if (ED_head_label(e)) { pt = ED_head_label(e)->p; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agset(e, "head_lp", buf); } if (ED_tail_label(e)) { pt = ED_tail_label(e)->p; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agset(e, "tail_lp", buf); } } } } rec_attach_bb(g); agxbfree(&xb); if (HAS_CLUST_EDGE(g)) undoClusterEdges(g); *sp = s_arrows; *ep = e_arrows; }
static void vrml_ellipse(GVJ_t * job, pointf * A, int filled) { FILE *out = job->output_file; obj_state_t *obj = job->obj; node_t *n; edge_t *e; double z = obj->z; double rx, ry; int dx, dy; pointf npf, nqf; point np; int pen; gdImagePtr brush = NULL; rx = A[1].x - A[0].x; ry = A[1].y - A[0].y; switch (obj->type) { case ROOTGRAPH_OBJTYPE: case CLUSTER_OBJTYPE: break; case NODE_OBJTYPE: n = obj->u.n; if (shapeOf(n) == SH_POINT) { doSphere (job, n, A[0], z, rx, ry); return; } pen = set_penstyle(job, im, brush); npf = vrml_node_point(job, n, A[0]); nqf = vrml_node_point(job, n, A[1]); dx = ROUND(2 * (nqf.x - npf.x)); dy = ROUND(2 * (nqf.y - npf.y)); PF2P(npf, np); if (filled) gdImageFilledEllipse(im, np.x, np.y, dx, dy, color_index(im, obj->fillcolor)); gdImageArc(im, np.x, np.y, dx, dy, 0, 360, pen); if (brush) gdImageDestroy(brush); fprintf(out, "Transform {\n"); fprintf(out, " translation %.3f %.3f %.3f\n", A[0].x, A[0].y, z); fprintf(out, " scale %.3f %.3f 1\n", rx, ry); fprintf(out, " children [\n"); fprintf(out, " Transform {\n"); fprintf(out, " rotation 1 0 0 1.57\n"); fprintf(out, " children [\n"); fprintf(out, " Shape {\n"); fprintf(out, " geometry Cylinder { side FALSE }\n"); fprintf(out, " appearance Appearance {\n"); fprintf(out, " material Material {\n"); fprintf(out, " ambientIntensity 0.33\n"); fprintf(out, " diffuseColor 1 1 1\n"); fprintf(out, " }\n"); fprintf(out, " texture ImageTexture { url \"node%d.png\" }\n", n->id); fprintf(out, " }\n"); fprintf(out, " }\n"); fprintf(out, " ]\n"); fprintf(out, " }\n"); fprintf(out, " ]\n"); fprintf(out, "}\n"); break; case EDGE_OBJTYPE: e = obj->u.e; /* this is gruesome, but how else can we get z coord */ if (DIST2(A[0], ND_coord_i(e->tail)) < DIST2(A[0], ND_coord_i(e->head))) z = obj->tail_z; else z = obj->head_z; fprintf(out, "Transform {\n"); fprintf(out, " translation %.3f %.3f %.3f\n", A[0].x, A[0].y, z); fprintf(out, " children [\n"); fprintf(out, " Shape {\n"); fprintf(out, " geometry Sphere {radius %.3f }\n", (double) rx); fprintf(out, " appearance USE E%d\n", e->id); fprintf(out, " }\n"); fprintf(out, " ]\n"); fprintf(out, "}\n"); } }
static void vrml_polygon(GVJ_t *job, pointf * A, int np, int filled) { FILE *out = job->output_file; obj_state_t *obj = job->obj; node_t *n; edge_t *e; double z = obj->z; pointf p, mp; gdPoint *points; int i, pen; gdImagePtr brush = NULL; double theta; switch (obj->type) { case ROOTGRAPH_OBJTYPE: fprintf(out, " Background { skyColor %.3f %.3f %.3f }\n", obj->fillcolor.u.rgba[0] / 255., obj->fillcolor.u.rgba[1] / 255., obj->fillcolor.u.rgba[2] / 255.); Saw_skycolor = TRUE; break; case CLUSTER_OBJTYPE: break; case NODE_OBJTYPE: n = obj->u.n; pen = set_penstyle(job, im, brush); points = N_GNEW(np, gdPoint); for (i = 0; i < np; i++) { mp = vrml_node_point(job, n, A[i]); points[i].x = ROUND(mp.x); points[i].y = ROUND(mp.y); } if (filled) gdImageFilledPolygon(im, points, np, color_index(im, obj->fillcolor)); gdImagePolygon(im, points, np, pen); free(points); if (brush) gdImageDestroy(brush); fprintf(out, "Shape {\n"); fprintf(out, " appearance Appearance {\n"); fprintf(out, " material Material {\n"); fprintf(out, " ambientIntensity 0.33\n"); fprintf(out, " diffuseColor 1 1 1\n"); fprintf(out, " }\n"); fprintf(out, " texture ImageTexture { url \"node%d.png\" }\n", n->id); fprintf(out, " }\n"); fprintf(out, " geometry Extrusion {\n"); fprintf(out, " crossSection ["); for (i = 0; i < np; i++) { p.x = A[i].x - ND_coord_i(n).x; p.y = A[i].y - ND_coord_i(n).y; fprintf(out, " %.3f %.3f,", p.x, p.y); } p.x = A[0].x - ND_coord_i(n).x; p.y = A[0].y - ND_coord_i(n).y; fprintf(out, " %.3f %.3f ]\n", p.x, p.y); fprintf(out, " spine [ %d %d %.3f, %d %d %.3f ]\n", ND_coord_i(n).x, ND_coord_i(n).y, z - .01, ND_coord_i(n).x, ND_coord_i(n).y, z + .01); fprintf(out, " }\n"); fprintf(out, "}\n"); break; case EDGE_OBJTYPE: e = obj->u.e; if (np != 3) { static int flag; if (!flag) { flag++; agerr(AGWARN, "vrml_polygon: non-triangle arrowheads not supported - ignoring\n"); } } if (IsSegment) { doArrowhead (job, A); return; } p.x = p.y = 0.0; for (i = 0; i < np; i++) { p.x += A[i].x; p.y += A[i].y; } p.x = p.x / np; p.y = p.y / np; /* it is bad to know that A[1] is the aiming point, but we do */ theta = atan2((A[0].y + A[2].y) / 2.0 - A[1].y, (A[0].x + A[2].x) / 2.0 - A[1].x) + M_PI / 2.0; /* this is gruesome, but how else can we get z coord */ if (DIST2(p, ND_coord_i(e->tail)) < DIST2(p, ND_coord_i(e->head))) z = obj->tail_z; else z = obj->head_z; /* FIXME: arrow vector ought to follow z coord of bezier */ fprintf(out, "Transform {\n"); fprintf(out, " translation %.3f %.3f %.3f\n", p.x, p.y, z); fprintf(out, " children [\n"); fprintf(out, " Transform {\n"); fprintf(out, " rotation 0 0 1 %.3f\n", theta); fprintf(out, " children [\n"); fprintf(out, " Shape {\n"); fprintf(out, " geometry Cone {bottomRadius %.3f height %.3f }\n", obj->penwidth * 2.5, obj->penwidth * 10.0); fprintf(out, " appearance USE E%d\n", e->id); fprintf(out, " }\n"); fprintf(out, " ]\n"); fprintf(out, " }\n"); fprintf(out, " ]\n"); fprintf(out, "}\n"); break; } }
main(int argc, char *argv[]) { Agraph_t **gs; Agraph_t **ccs; Agraph_t *g; Agraph_t *gp; char *fname; FILE *fp; int cnt; int i; init(argc, argv); if (!Files) { fprintf(stderr, "No input files given\n"); exit(1); } PSinputscale = POINTS_PER_INCH; if (doComps) { if (verbose) fprintf(stderr, "do Comps\n"); while (fname = *Files++) { fp = fopen(fname, "r"); if (!fp) { fprintf(stderr, "Could not open %s\n", fname); continue; } g = agread(fp); fclose(fp); if (!g) { fprintf(stderr, "Could not read graph\n"); continue; } printf("%s %d nodes %d edges %sconnected\n", g->name, agnnodes(g), agnedges(g), (isConnected(g) ? "" : "not ")); gs = ccomps(g, &cnt, "abc"); for (i = 0; i < cnt; i++) { gp = gs[i]; printf(" %s %d nodes %d edges\n", gp->name, agnnodes(gp), agnedges(gp)); } } } else { gs = N_GNEW(nFiles, Agraph_t *); cnt = 0; while (fname = Files[cnt]) { fp = fopen(fname, "r"); if (!fp) { fprintf(stderr, "Could not open %s\n", fname); exit(1); } g = agread(fp); fclose(fp); if (!g) { fprintf(stderr, "Could not read graph\n"); exit(1); } if (!single) { graph_init(g); ptest_initGraph(g); } initPos(g); /* if (Verbose) dumpG (g); */ gs[cnt++] = g; } if (single) { Agraph_t *root; Agnode_t *n; Agnode_t *np; Agnode_t *tp; Agnode_t *hp; Agedge_t *e; Agedge_t *ep; root = agopen("root", 0); agedgeattr(root, "pos", ""); for (i = 0; i < cnt; i++) { g = gs[i]; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (agfindnode(root, n->name)) { fprintf(stderr, "Error: node %s in graph %d (%s) previously added\n", n->name, i, Files[i]); exit(1); } np = agnode(root, n->name); ND_pos(np)[0] = ND_pos(n)[0]; ND_pos(np)[1] = ND_pos(n)[1]; ND_coord_i(np).x = ND_coord_i(n).x; ND_coord_i(np).y = ND_coord_i(n).y; } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { tp = agfindnode(root, n->name); for (e = agfstout(g, n); e; e = agnxtout(g, e)) { hp = agfindnode(root, e->head->name); ep = agedge(root, tp, hp); ED_spl(ep) = ED_spl(e); } } } graph_init(root); ptest_initGraph(root); ccs = ccomps(root, &cnt, 0); packGraphs(cnt, ccs, root, margin, doEdges); if (!doEdges) copyPos(root); else State = GVSPLINES; attach_attrs(root); for (i = 0; i < cnt; i++) { agdelete(root, ccs[i]); } agwrite(root, stdout); } else { packGraphs(cnt, gs, 0, margin, doEdges); if (doEdges) State = GVSPLINES; for (i = 0; i < cnt; i++) { if (!doEdges) copyPos(gs[i]); attach_attrs(gs[i]); agwrite(gs[i], stdout); } } } }