Add file describing how to add a new layout to graphviz
authorerg <devnull@localhost>
Sat, 19 Apr 2008 15:57:38 +0000 (15:57 +0000)
committererg <devnull@localhost>
Sat, 19 Apr 2008 15:57:38 +0000 (15:57 +0000)
doc/addingLayout.txt [new file with mode: 0644]

diff --git a/doc/addingLayout.txt b/doc/addingLayout.txt
new file mode 100644 (file)
index 0000000..99e9263
--- /dev/null
@@ -0,0 +1,126 @@
+New layout: xxx
+
+Entry points: 
+
+========================
+
+  void xxx_layout(Agraph_t * g)
+
+    Initialize the graph.
+       - If the algorithm will use the common edge routing code, it should
+    call setEdgeType (g, ...);
+
+       - For each node, call common_init_node and gv_nodesize.
+    If the algorithm will use spline_edges() to route the edges, the
+    node coordinates need to be stored in ND_pos, so this should be
+    allocated here.
+
+       - For each edge, call common_init_edge
+
+       - The algorithm should allocate whatever other data structures it
+    needs. This can involve fields in the A*info_t fields. In addition,
+    each of these fields contains a void* alg; subfield that the algorithm
+    can use the store additional data. 
+         Once we move to cgraph, this will all be replace with 
+    algorithm specific records.
+
+    Layout the graph. When finished, each node should have its coordinates
+  stored in points in ND_coord_i(n), each edge should have its layout
+  described in ED_spl(e). Note: If spline_edges() is used, the coordinates
+  in ND_pos will be correctly copied into ND_coord_i.
+
+    If the algorithm only works with connected components, the code can
+  use the pack library to get components, lay them out individually, and
+  pack them together based on user specifications. A typical schema is
+  given below. One can look at the code for twopi, circo, neato or fdp
+  for more detailed examples.
+
+        Agraph_t **ccs;
+        Agraph_t *sg;
+        Agnode_t *c = NULL;
+        int ncc;
+        int i;
+
+        ccs = ccomps(g, &ncc, 0);
+        if (ncc == 1) {
+            /* layout nodes of g */
+            adjustNodes(g);  /* if you need to remove overlaps */
+            spline_edges(g); /* generic edge routing code */
+
+        } else {
+            pack_info pinfo;
+            pack_mode pmode = getPackMode(g, l_node);
+
+            for (i = 0; i < ncc; i++) {
+                sg = ccs[i];
+                /* layout sg */
+                adjustNodes(sg);  /* if you need to remove overlaps */
+            }
+            spline_edges(g);  /* generic edge routing */
+
+            /* initialize packing info, e.g. */
+            pinfo.margin = getPack(g, CL_OFFSET, CL_OFFSET);
+            pinfo.doSplines = 1;
+            pinfo.mode = pmode;
+            pinfo.fixed = 0;
+            packSubgraphs(ncc, ccs, g, &pinfo);
+        }
+        for (i = 0; i < ncc; i++) {
+            agdelete(g, ccs[i]);
+        }
+
+        free(ccs);
+
+    Be careful in laying of subgraphs if you rely on attributes that have
+  only been set in the root graph. With connected components, edges can
+  be added with each component, before packing (as above) or after the
+  components have been packed (see circo).
+
+    It good to check for trivial cases where the graph has 0 or 1 nodes,
+  or no edges.
+
+    At the end of xxx_layout, call
+
+       dotneato_postprocess(g);
+
+======================
+
+  void xxx_cleanup(Agraph_t * g)
+
+    Free up any resources allocated in the layout.
+
+    Finish with calls to gv_cleanup_node and gv_cleanup_edge for
+  each node and edge. This cleans up splines labels, ND_pos, shapes
+  and 0's out the A*info_t, so these have to occur last, but could be
+  part of explicit xxx_cleanup_node and xxx_cleanup_edge, if desired.
+    At the end, we usually include
+
+  if (g != g->root) memset(&(g->u), 0, sizeof(Agraphinfo_t));
+
+  libgvc does a final cleanup to the root graph, freeing any drawing,
+  freeing its label, and zeroing out Agraphinfo_t of the root graph.
+
+==================
+
+Most layouts use auxiliary routines similar to neato, so
+the entry points can be added in plugin/neato_layout
+
+Add to gvlayout_neato_layout.c:
+
+gvlayout_engine_t xxxgen_engine = {
+    xxx_layout,
+    xxx_cleanup,
+};
+
+and line
+
+    {LAYOUT_XXX, "xxx", 0, &xxxgen_engine, &neatogen_features},
+
+to gvlayout_neato_types and new emum
+
+    LAYOUT_XXX
+
+to layout_type in that file.
+
+Changes need to be made to any applications, such as gvedit, that
+statically know about layout algorithms.