Welcome to the documentation for Dynagraph (As Dynagraph is always changing, be sure this matches the version of Dynagraph you are using!)

  1. Introduction
  2. The front ends
    1. Dynagraph for Grappa
    2. Dynagraph for Windows
  3. The executable
    1. Command line options
    2. The incrface language
    3. Incrface example
  4. The C++ library
    1. C++ programming model
    2. How to use Dynagraph with the incrface library
    3. How to use Dynagraph without the incrface library
    4. C++ API reference
  5. The COM library
    1. COM programming model
    2. How to use the COM library
  6. API reference
    1. Attributes common to graphs, nodes and edges
    2. Graph attributes
    3. Node attributes
    4. Edge attributes
  7. Links


Dynagraph is a platform-independent graph layout engine. Dynagraph calculates geometric coordinates for nodes and edges of a graph diagram. Dynagraph responds to changes in the graph - insertion, deletion, or modification of nodes and edges. It balances stability (unchanged parts of the graph should not change much) with readability (edges should be short and direct, and should cross each other as little as possible).

Dynagraph itself does not render to a screen, graphic file, or printer, nor does it provide a GUI for editing graphs. Dynagraph only computes the coordinates, and front ends such as Dynagraph for Windows (dgwin) and Dynagraph for Grappa handle all the platform-specific rendering and GUI functions. (This document briefly describes how to use these front ends.) Since Dynagraph shares its file format and most of the attributes with the other graphviz tools (dot,neato,lefty), those tools can also be used to render Dynagraph output.

This document is mostly concerned with how to connect programs to the Dynagraph layout engines. Dynagraph supports three ways to do this:

Although the programming models differ, the API and layout attributes are essentially the same.

The front ends

Most likely you will not be writing your own front end to draw to the screen, graphics files, etc. We provide two front ends that you may want to use: dggrappa, a version of Grappa adapted for Dynagraph; and Dynagraph for Windows, which integrates Dynagraph with other OLE (ActiveX) applications such as the Microsoft Office suite.

Dynagraph for Grappa

Dynagraph for Grappa (dggrappa) (source available here) is a slightly modified version of Grappa with an extra module to interpret and generate the incrface language. The dggrappa application spawns the Dynagraph executable in a separate process and communicates with it using pipes. Drawing commands in Grappa send incrface commands to Dynagraph; Dynagraph returns incrface events to which Grappa responds by updating the canvas. For example, pressing the shift key while clicking on the background or dragging between nodes sends "insert" commands to Dynagraph; they return as "insert" events and Grappa draws the new nodes and edges. Also dggrappa can be told to copy its standard input to the Dynagraph input (with "-i -"). Then you or your application can enter or change the graph by inputting incrface language commands to dggrappa.

The dggrappa application is a class called att.dggrappa.DGDemo. It requires one command-line parameter: the path to the Dynagraph executable. It will spawn Dynagraph with the command line parameter -d, because Grappa uses dot-like coordinates (with the difference that the lower-left corner is not necessarily 0,0). By default it specifies the graph attributes [resolution="1,1",separation="24,24",engines="shapegen,fdp,voronoi,visspline"]

Dynagraph for Grappa command line options

-i filename specify input file
Specifies a file to read incrface commands from. If filename is a single dash ("-"), dggrappa will copy its standard input to the standard input of the Dynagraph process.
-a attr=value
(Exactly one space.) Sets a graph attribute that will be sent in the initial open graph command. Particularly useful for specifying the layout engines to use.
-l filename specify log file
Tells dggrappa to log what it's sending to the Dynagraph process.
-b big graph exploring mode
This is for looking at graphs that are too large to visualize. Shows the portion of the graph that is within N edges of what is selected.
-d graph drawing mode
This is the default. Holding shift while clicking on the background creates nodes; holding shift while dragging between nodes creates edges.
-p show the pipes
Tells dggrappa to write to standard output a transcript of what it's sending and receiving on the pipes to Dynagraph.

Dynagraph for Windows

Dynagraph for Windows (dgwin) (binaries and source available through dynagraph.org) is a full-featured, OLE-capable graph drawing application and control. It can be embedded in OLE applications such as the Microsoft Office suite, Web pages, and Visual Basic programs. It wraps the Dynagraph library in COM interfaces, so that the layout and content can be controlled from any ActiveX compatible language. Dynagraph for Windows is based on a general control container library called Montage, which can be used for creating other new OLE document types and applications.

Driving dgwin with text

At this time there is no built-in way to connect dgwin to a pipe to receive incrface commands. If this is the desired way to control the layout, the best way is to create an instance of the singleton Dynagraph.IncrClient class (CLSID_DGIncrClient). This class is intended to spawn an external graph server, and the method IDGIncrClient::Write sends text to that server. However, if the method IDGIncrClient::StartServer was not called, then Write sends the text directly to the incrface parser. Call IDGStringAttributes::get_Name on the layout engine to find out the name of the graph to use in the incrface commands.

Driving dgwin via COM

Dynagraph for Windows consists of a large number of small objects. It is designed for super-modularity: not only can the visual elements be changed (e.g. Word documents for nodes), but the user interface itself can be changed, replacing, say, what happens when the user right-clicks an edge. The Montage object is a blank canvas with no interaction at all; on top of this are built configurations which add the visual and interactive behaviors we have come to expect from Windows programs. Instantiate the class DGM.Diagram (CLSID_DynagraphControl) to get a full-featured graph drawing control.

Every node and edge in a dgwin diagram has quite a few objects backing it up:

There are helpful functions to navigate between these objects in the Shared directory of the dgwin source, especially in nodeAndSite.{h,cpp}.

While it is possible to construct all of these objects and connect them directly, it requires quite a lot of code, especially considering that most of these also require a persistor object in order to be saved and loaded! The DGM.Drawer object handles all of this work. It holds pointers to OLE data objects which provide the controls to use for nodes, edges, and labels. (OLE data objects implement IDataObject; these are the basis of clipboard and drag-and-drop operations.) It also holds pointers to the Montage canvas and to the Dynagraph layout engine, as well as to a Montage data unpacker, which knows how to read the data objects.

If your application is going to use the default nodes and edges, it can use the Drawer as it is. First you'll need pointers to the layout engine and to the DGM Drawer object. Their internal names are "Graph Layout Engine" and "Graph Drawer"; get pointers to them by binding item monikers with these names or by calling IOleItemContainer::GetObject. Next, create the layout objects using IDGGraph::new_Node and ::new_Edge on the layout engine. Set any layout parameters using the interfaces IDGDrawnNode and IDGDrawnEdge on the layout objects. Then use the IDGMDrawer::NewNode and ::NewEdge methods to create the rest of the objects listed above.

To move objects around and to delete them, you have a choice of methods. The easiest way is probably to call methods on the Dynagraph objects. For example, calling IDGDrawnNode::Delete or IDGEdge::Delete will delete the object. To change a node's position, call IDGDrawnNode::put_Pos. But wait a second: that's a POINTD! Yes, Dynagraph uses floating point coordinates, and though the library is resolution-independent, Dynagraph for Windows uses units of one centimeter. Also, you'll find no "size" input; instead nodes have polygonal shapes, over which the DGM.NodeShadow expects to have control.

So the proper way to change the size of a node is to fire an event on the site. ("I thought objects fired their own events," you object. Well, COM actually leaves it open for other objects to fire those events. See or use Shared/fire*.h.) The relevant events are on IMCCSiteOwner; these make it possible for the Edit mode to move and delete objects without knowing about Dynagraph. And IMCCSiteOwner::Move accepts pixel or HIMETRIC (0.01cm) point, size, or rectangle coordinates.

The executable

The Dynagraph executable can be run in two modes:

Command line options

-v (--version) print version number
Prints the version number only. Dynagraph version numbers consist of four numbers separated by periods. The final number is a build number—versions that differ only by this last number should only vary in their reliability, not in their functionality.
-h (--help) print help
Prints a summary of command line options and syntax only.
-d use dot-compatible coordinates
Dynagraph internally uses dimensionless coordinates, but dot used points for coordinates and inches for node sizes. With this option, the node width, height, and labelsize attributes will be multiplied by 72. This option also affects default attributes, setting the default resolution to 1x5 instead of 0.1x0.1; the default separation to 24x24 instead of 0.5x0.5; and the default minimum width and height to 54x36 instead of 1.5x1.
-a attr=value set default graph attribute
Sets the initial value of a graph attribute for all graphs that are opened in this session.
-i filename specify input dot file
Specifies a file for batch layout.
-s filename specify input incrface file
Specifies an input file in the incrface language.
-oN filename output stream N to filename
Writes report stream N to filename. See -r report.
-oL filename
Outputs the layout at each step to filename1.dot, filename2.dot, etc. A dot file will be generated every time a re-layout happens; that is, whenever a change happens and the lock count is zero, or after changes when the lock count drops to zero.
-raN report on a to stream N
Dynagraph can write logs to up to 10 files (output filenames specified with -o output). a specifies one or more report types from the following:
i Dynagraph input (raw)
k Dynagraph input (cooked: post-interpreter and contains "pulse" timing information to reproduce the timing of input)
o Dynagraph output
c Crossing optimization statistics
t Time usage breakdown
d Dynadag tallies
g Dump graph in dotfile format after every step
q Dump input queue before each step
r Output readability statistics
s Output stability statistics
p Report on progress
b Bug of the day: used for random debugging
n Inner engine input (useful for debugging emphasizeflow)
u Inner engine output (useful for debugging emphasizeflow)
-e N specify random number seed
Random numbers are not used very much in layout (except in fdp). This has more effect on -wr wait random amount.
-w[r] N wait [randomly up to] N nanoseconds before commands
Waits before each line of incrface code, allowing the layout engine to run instead of immediately interrupting it. (May someday be) useful for debugging.

Command interface - incrface

In this interface, the client and server communicate requests and modifications over pipes using a command language. The language is the same for client requests and server events, with the exception that the server does not emit the "segue" command. Many commands can accept attributes in the dot syntax, i.e. [attr=value,attr2="value with spaces or other parser-confusing stuff"]

This language can also be used for other incremental graph purposes. For example, a slightly augmented version is used by the Dinograph large graph server.

open graph L [attrs]
Opens a layout graph named L.
modify graph L [attrs]
Applies the attributes to L
close graph L
Closes the layout graph L.
insert node L N [attrs]
Creates a node named N in graph L.
insert edge L E [attrs]
Creates an edge named E in graph L.
modify node L N [attrs]
Applies the attributes to N.
modify edge L E [attrs]
Applies the attributes to E.
delete node L N
Removes N from the layout.
delete edge L E
Removes E from the layout.
pulse graph L [attrs]
A pulse is a timing event on the stream of changes itself. The attributes provide the specifics. Currently this is used to communicate when Dynagraph has been interrupted or should be interrupted. DynaDAG uses the attribute "phase" (values "update","untangle", or "xopt") and the attribute "step" (currently always "done" specifying that the phase is over). On input, the pulse command causes DynaDAG to interrupt (no sooner than) the specified moment. On output, one can determine from the pulse command when DynaDAG was interrupted. At present this function is mostly useful for debugging, in order to reproduce bugs that depend on the timing of input.
lock graph L
Increments the lock count on L. While the count is greater than zero, Dynagraph will not do any layouts and will not output. On output, Dynagraph uses lock and unlock to mark a group of changes so that the client can respond more efficiently.
unlock graph L
Decrements the lock count on L. If the count returns to zero, does a new layout based on all queued changes.
segue graph L
dot-language graph
(The line break between the command and the graph is required.) Graph specifies a full graph in the dot graph language; Dynagraph will make all necessary changes to transform the current graph to that specified.
request graph L
Requests the current state of the layout L.
request node L N
Requests the current state of L's node N
request edge L E
Requests the current state of L's edge E
fulfil graph L
dot-language graph
Response to the "request graph" command. Dynagraph ignores this as input, and clients probably won't emit it (unless they are servers themselves).
fulfil node L N [attrs]
Response to the "request node" command.
fulfil edge L E [attrs]
Response to the "request edge" command.

Incrface example

What follows is a transcript of a simple interaction with Dynagraph. In this example, the input text is in bold, the output text is normal, and comments are in italics.

open graph V
open graph V [
Dynagraph can serve multiple layouts at once; this example uses the name "V" because that's what dggrappa expects. Dynagraph is unit-independent but defaults to settings appropriate for measurement in centimeters. It also defaults to DynaDAG and a few helpers as the layout engines.
insert node V a [pos="5,5"]
lock graph V
insert node V a [shape=ellipse,pos="5.0,5.0",width=1.500000,height=1.000000,lines="b3 -0.750000,0.000000 -0.750000,-0.276142 -0.414214,-0.500000 0.000000,-0.500000 0.414214,-0.500000 0.750000,-0.276142 0.750000,0.000000 0.750000,0.276142 0.414214,0.500000 0.000000,0.500000 -0.414214,0.500000 -0.750000,0.276142 -0.750000,0.000000;"]
That really long attribute is a bezier approximation of an ellipse, the default shape.
unlock graph V
insert node V b
lock graph V
modify graph V [bb="4.3,4.5,7.8,6.5",changerect="6.3,4.5,7.8,5.5"]
insert node V b [shape=ellipse,pos="7.0,5.0",width=1.500000,height=1.000000,lines="b3 -0.750000,0.000000 -0.750000,-0.276142 -0.414214,-0.500000 0.000000,-0.500000 0.414214,-0.500000 0.750000,-0.276142 0.750000,0.000000 0.750000,0.276142 0.414214,0.500000 0.000000,0.500000 -0.414214,0.500000 -0.750000,0.276142 -0.750000,0.000000;"]
unlock graph V
New nodes get put next to one another in a row.
insert edge V e a b
lock graph V
modify graph V [bb="6.3,3.0,7.8,6.5",changerect="7.0,4.0,7.0,4.5"]
insert edge V e a b [pos="7.0,4.5 7.0,4.3 7.0,4.2 7.0,4.0"]
modify node V a [pos="7.0,5.0"]
modify node V b [pos="7.0,3.5"]
unlock graph V
Dynagraph moved node b to 0.5cm below node a, and drew the new edge as a straight line . (Why it moved node a to node b's old position is not so clear...)
delete node V a
lock graph V
modify graph V [bb="6.3,3.0,7.8,5.0",changerect="6.3,4.0,7.8,5.5"]
delete edge V e
delete node V a
unlock graph V
Deleting the node implicitly deleted the edge connected to it. The other node was unaffected.

The C++ library

The Dynagraph library can be linked to a C++ program. The API for connecting with a Dynagraph layout server is defined in common/Dynagraph.h and auxiliary headers. There are two main libraries: the core library (in the subdirectory common) and the incrface library. Then there are four layout engines in separate libraries: dynadag, fdp, shortspline (visspline), and voronoi. (The graphsearch large graph server is undocumented.) This document does not address platform-specific issues such as how to build Dynagraph or link it. That information is available elsewhere on the Dynagraph web site.

C++ programming model

The Dynagraph library provides a C++ API that blurs the difference between batch and incremental layout. (This is also the most powerful of the APIs, as this is the API that's used internally and it's not mediated by translation code.) You can choose whether or not to use the incrface library, which provides both naming services and the ability to receive commands using the incrface language.

Unfortunately, this whole section of the documentation is both incomplete and out of date, as are the example source files. :-(

How to use Dynagraph with the incrface library

To be described.

How to use the library without the incrface library

Sorry, due to recent architectural innovations, this section is out of date!

Here are the steps required to use the Dynagraph library from a C++ program directly, bypassing the incrface library (from example_no_incrface.cpp). This still uses the function createLayoutServer from the incrface library to create the layout server. The composition of multiple servers into one using the class CompoundServer is a detail which most applications won't need to change, but that function too can be re-written.

  1. Include the main Dynagraph header and the header for createLayoutServer:

    #include "common/Dynagraph.h"
    #include "incrface/createLayoutServer.h"

  2. For each layout, you will need two graphs to hold the data, a ChangeQueue to track changes, and an instance of the layout server. Create two instances of the Layout class defined in Dynagraph.h. This class is a graph which holds information about the layout preferences and geometry. We will call these graphs layout and current; layout is where we create new elements, and current is the subgraph which represents what is showing in the layout. Make current a subgraph of layout by specifying layout in the constructor call, i.e.

    Layout layout,current(&layout);

  3. Since Dynagraph is resolution-independent, you must set the resolution, separation and label separation as appropriate. Use the gd<> function to access data in a graph by its type. Since these parameters are in the GraphGeom portion of the graph data, preparation for centimeter coordinates might look like:

    gd<GraphGeom>(&layout).resolution = Coord(0.1,0.1);
    gd<GraphGeom>(&layout).separation = Coord(0.5,0.5);

  4. Create an instance of the ChangeQueue class, which will hold changes we are making as well as ones made by the layout server. This needs to know both the layout and current graphs:

    ChangeQueue queue(&layout,&current);

  5. Specify the layout engines you want by setting the string attribute:

    gd<StrAttrs>(&layout)["engines"] = "shapegen,fdp,voronoi,visspline";

  6. Create the layout engines by calling createLayoutServer:

    Server *server = createLayoutServer(&layout,&current)

  7. Issue commands to Dynagraph by first making the change (except in the case of deletion), then marking the change in the ChangeQueue, then running the server's Process method. Let's create nodes at (10,10) and (15,10):

    Layout::Node *m = layout.create_node(),*n = layout.create_node();
    gd<NodeGeom>(m).pos = Coord(10,10);
    gd<NodeGeom>(n).pos = Coord(15,10);

  8. Between runs it's important to clear the ChangeQueue with the Okay command. Its sole parameter tells it whether to erase the nodes and edges marked for deletion. This choice depends upon whether there's a need for nodes and edges to live outside the current layout. For this example, there is no reason for them to:


  9. To draw an edge between two nodes is similar:

    Layout::Edge *e = layout.create_edge(m,n).first;
    // ... read changes from the queue ...

  10. To move a node:

    gd<NodeGeom>(n).pos = Coord(5,5);

  11. Deletion is a little different, because the node or edge still has to exist while the engine is processing it. So mark it with DelNode or DelEdge and then use ChangeQueue.Okay(true) or Layout::erase after the engine has run. Also note that deleting a node causes any edges attached to it to be deleted.

    // ... read changes from the queue ...

  12. Most requests will cause many more changes. So it is important to read the ChangeQueue after every run of the layout server. For example, to read the moved nodes:

    Layout::node_iter ni;
    for(ni = queue.modN.nodes().begin(); ni!=queue.modN.nodes().end(); ++ni)
    ;// move graphical object associated with *ni to gd<NodeGeom>(*ni).pos;

C++ API reference

The COM library

To come: how to attach to the Dynagraph COM library (comdg) to do layouts without using Montage and the whole of Dynagraph for Windows.

COM programming model

How to use the COM library

API reference

There are three APIs to Dynagraph: the incrface language, whose string attributes (only accessed in dynagraph/common/stringsIn.cpp, stringsOut.cpp, and ColorByAge.cpp) are mostly a subset of the dot language's attributes; the C++ API; and the COM API. This reference defines the parameters which are common to all three; specifics about how to use each API should have been laid out in the last three sections.

If the C++ entry says "use string attribute", that means you should manipulate the string name, e.g. with incrface:

StrAttrs attrs;
attrs["shape"] = "ellipse";

Or without:
StrAttrs attrs;
attrs["shape"] = "ellipse";

If the COM entry says this, use IDGStringAttributes, e.g. in ATL:
CComQIPtr<IDGStringAttributes> nstrings = n;

Attributes common to graphs, nodes, and edges

[ graph attrs   ¯---    node attrs   ---    edge attrs ]
incrface attribute C++ class and field COM interface and method
(out) lines = "bB x1,y1 x2,y2 ...; bB x,y..."
(in for nodes) boundary = "x0,y0 x1,y1 x2,y2 ..."
(in,out for edges) pos = "x0,y0 x1,y1 x2,y2 ..."
(out) struct Drawn : Lines
(in) Region NodeGeom::region
Line EdgeGeom::pos
interface IDGLayout
[propget] HRESULT Lines([out,retval] DGSHAPESDESC **ret);
interface IDGDrawnNode
[propput] HRESULT Shape([in] DGSHAPESDESC *shapes);
[propget] HRESULT Shape([out,retval] DGSHAPESDESC **ret);
interface IDGDrawnEdge
HRESULT SetPoints([in] DGSHAPEDESC *val);
HRESULT GetPoints([out,retval] DGSHAPEDESC **ret);

(in,out) On output, the lines or Bezier curves to draw. On input, the node shape to use for edge clipping, or a hint for where to draw the edge. In the string attribute, B specifies the Bezier degree, either 1 for lines or 3 for cubic Bezier curves. On the graph, this attribute is used only for debugging. On a node, this is a valid input only if shape generation is turned off; only the first poly(sp)line is used for edge clipping; and the points are relative to the node position. On an edge, only one poly(sp)line must be specified (note the different type of the C++ and COM versions). This parameter is ignored (?!) as an edge input in the string and COM versions, and in C++ unless EdgeGeom::manualRoute is true.

Graph attributes

[ common attrs   ---    node attrs   ---    edge attrs ]

Graph attributes control general parameters about the layout, as well as what layout engines are used. Many graph attributes can not be changed after the layout is opened.

incrface attribute C++ class and field COM interface and method
layout = dynadag|fdp use string attribute use string attribute

(in) Specifies which type of layout to perform. At present DynaDAG (directed) and FDP (undirected) layout are supported; DynaDAG is the default. Layout cannot (currently) be changed after the graph is opened.

coordtranslation = true|false use string attribute use string attribute

(in) By default, DynaDAG lays out graphs from top to bottom; that is, edges point downward. (Dynagraph and this document assume that Y increases upward, as it does in the real world but often not on computer screens. :-) However, if coordinate translation is enabled, the graph can be rotated so that edges point rightward, downward, or leftward. This attribute works in conjunction with the rankdir attribute. It or rankdir must be set when the graph is opened in order for coordinate transation to be enabled. This feature is also available for undirected layout, but is of dubious worth there.

rankdir = TB|LR|BT|RL Orientation Translation::orientation interface IDGEngine
[propget] HRESULT Orientation([out,retval] enum DG_ORIENTATION *ret);
[propput] HRESULT Orientation([in] enum DG_ORIENTATION val);

(in) Rotates the layout from the default of top-down (TB). Coordinate translation must be enabled for this attribute to have effect: coordtranslation or rankdir must be set upon opening the graph. This attribute can be changed after the graph is opened, causing the full layout to rotate.

findchangerects = true|false use string attribute use string attribute

(in) If this feature is enabled upon opening the graph, Dynagraph will calculate the minimal rectangle that contains all inserted, deleted, and moved nodes and edges in the changerect attribute. Default: false

shapegen = true|false use string attribute use string attribute

(in) Enables/disables shape generation. The shape generator uses the nodes' shape attribute and related attributes to draw their shapes. Otherwise shapes should be specified using the nodes' lines attribute. This attribute must be set upon opening the graph, and cannot be changed later. Default: true

nodesuppression = true|false use string attribute use string attribute

(in) Enables/disables node suppression. When a node is suppressed using the suppressed attribute, it is not drawn, takes up very little space, and its edges are cut short at the other end. This attribute must be set upon opening the graph, and cannot be changed later. Default: true

flowemphasizable = true|false use string attribute use string attribute

(in) DynaDAG only. Enables the emphasizeflow attribute for edges. Setting emphasizeflow when opening the graph also enables this feature. This attribute must be set upon opening the graph, and cannot be changed later. Default: true

emphasizeflow = true|false bool GraphGeom::s_edges N/A

Setting this is the equivalent of setting the edge attribute emphasizeflow=true for all edges in the graph. Either this or flowemphasizable must be set upon opening the graph in order to enable this feature. Default: false

defaultsize = "x,y" Coord GraphGeom::defaultSize N/A

(in) The minimum size to use for nodes for which that parameter was not set. Because this is used when looking at the string attributes, this is only relevant for programs using incrface. Default: (1.5,1) without -d, (54,36) with.

resolution = "x,y" Coord GraphGeom::resolution interface IDGEngine
[propget] HRESULT Resolution([out,retval] POINTD *ret);
[propput] HRESULT Resolution([in] POINTD val);

(in) DynaDAG only. The smallest increment to recognize in the internal model. For example, specify 1,1 for integer precision. Default: (0.1,0.1) without -d, (1,1) with. If rankdir is LR or RL, then x and y are reversed.

separation = "x,y" Coord GraphGeom::separation interface IDGEngine
[propget] HRESULT Separation([out,retval] POINTD *ret);
[propput] HRESULT Separation([in] POINTD val);

(in) The amount of separation to leave between elements of the layout. For DynaDAG layout, x specifies the horizontal gap between nodes (and, if edgeseparation is not set, four times the gap between edges), and y specifies the amount by which to multiply the edge length to get the minimum vertical displacement. When rankdir is LR or RL, x specifies the vertical gap between nodes and y still specifies the edge length. Default: (0.5,0.5) without -d, (24,24) with.

edgeseparation = "x" N/A N/A

(in) If specified, sets the horizontal gap (or vertical if rankdir is LR or RL) between edges where they are running parallel. Otherwise, the gap is one quarter of separation.x.

intermediate = true|false bool GraphGeom::reportIntermediate N/A

(in) Whether DynaDAG should generate intermediate (crude) layouts—if set, DynaDAG will report node and edge positions as soon as it has calculated the Y positions and set up its internal models but before doing the more time-consuming untangling, X-coordinate assignment, and splining. Since the rough coordinates are much quicker to calculate, this allows immediate feedback to the user.

This attribute also enables layout interruption: if a command arrives after the intermediate layout has been generated but before layout is complete, DynaDAG will terminate layout and start again with the new requests accounted for.

N/A Coord GraphGeom::labelGap N/A

(in) The amount of space to leave between labels and nodes, e.g. if a label is on the right of a node, label.left = node.right+labelGap.x. Default: (0,0)

bb = "left,bottom,right,top" Bounds GraphGeom::bounds interface IDGLayout
[propget] HRESULT Bounds([out,retval] RECTD *ret);

(out) Reports the bounding box of the current layout. DynaDAG only.

changerect = "left,bottom,right,top" Bounds GraphGeom::changerect interface IDGLayout
[propget] HRESULT ChangeRect([out,retval] RECTD *ret);

(out) Supplies a rectangle which contains all of the changes just made to the layout. Only output if findchangerects was set for the graph on opening.

float GraphGeom::splineLevel interface IDGEngine
[propget] HRESULT SplineLevel([out,retval] enum DG_SPLINELEVEL *ret);
[propput] HRESULT SplineLevel([in] enum DG_SPLINELEVEL val);

(in) How to draw edges, specifically, how much of the spline-drawing process to complete. Although this parameter produces "interesting" results it is probably more useful for debugging than for stylistic purposes. This parameter is only implemented in dynadag.

vnode DG_SPLINELEVEL_VNODE DGSL_VNODE Draw straight lines between the nodes in the internal model.
bounds DG_SPLINELEVEL_BOUNDS DGSL_BOUNDS Draw the bounding polygon of the spline.
shortest DG_SPLINELEVEL_SHORTEST DGSL_SHORTEST Draw the shortest straight-line paths within the bounds.
spline DG_SPLINELEVEL_SPLINE DGSL_SPLINE Draw edges with Bezier curves (default).

colorbyage = true|false use string attribute use string attribute

This feature is intended to show the age of nodes in the graph by updating their colors based on the graph agecolors attribute. This or agecolors must be set on opening the graph in order to enable this feature.

agecolors = "color1,color2,..." use string attribute use string attribute

Parameter to the colorbyage "layout" engine. If this parameter exists, then any node which does not have a color will receive color=color1, any node which has color=color1 will receive color=color2, etc. Once nodes reach the final color they stop changing.

ticks = float
float GraphGeom::ticks use string attribute (!)

(in) Specifies the elapsed time, in seconds, after which Dynagraph should hurry up and try to get a result. Not used by current layout engines.

Node attributes

[ common attrs   ---    graph attrs   ---    edge attrs ]
incrface attribute C++ class and field COM interface and method
pos = "x,y" Position NodeGeom::pos interface IDGDrawnNode
[propget] HRESULT Pos([out, retval] POINTD *ppos);
[propput] HRESULT Pos([in] POINTD pos);

(in,out) Specifies the position coordinate of the node. This is the offset for the lines and boundary parameters. If the string parameter is blank or pos.valid==false or IDGDrawnNode::Optimize(VARIANT_TRUE) has been called, the engine will choose a new position for the node without regarding the old one.

flow = real number double NodeGeom::flow N/A

(in) Specifies the strength of flow for edges entering and leaving this node. If flow>0 then edges will enter and leave the edge at a common slope. Currently the magnitude of flow is not respected; in the future, edges will begin to adjust to the node's flow slope further off if flow is higher, or will have sharper bends if flow is lower.

suppressed = true|false bool NodeGeom::suppressed N/A

(in) If a node is suppressed, it will not be drawn and will not take up space in the layout. In addition, edges approaching this node are cut at a height of separation.y/3 and the cut portion will not take up space either. Node suppression must be enabled on the graph.

shape = shape-name use string attribute use string attribute

(in) Specifies the name of the base shape, which will select the other shape generation values (which can be overridden). These are a subset of those offered by dot. Default: ellipse.

none | plaintext No shape is generated.
ellipse The base shape is a Bezier spline approximation of an ellipse.
polygon The base shape is a polygon, by default four-sided.
hexagon sides = 6
box sides = 4
circle regular = true
isEllipse = true
diamond sides = 4
orientation = 90
doublecircle isEllipse = true
regular = true
peripheries = 1
doubleoctagon sides = 8
peripheries = 1
egg isEllipse = true
distortion = 1.3
orientation = 90
hexagon sides = 6
invtriangle sides = 3
orientation = 180
octagon sides = 8
parallelogram sides = 4
skew = 0.5
triangle sides = 3
tripleoctagon sides = 8
peripheries = 2

labelsize = "x,y" Coord PolyDef::interior_box interface DIDGShapeDefinition
[propget] HRESULT InsideWidth([out, retval] double *ret);
[propget] HRESULT InsideHeight([out, retval] double *ret);
HRESULT SetInside([in] double width,[in] double height);

(in) The size of the text to fit within this shape. For consistent heights with different line lengths, the shape will be stretched to fit a square whose size is the smaller of x and y, and then stretched again to fit the larger. Default: (0,0).

width = float
height = float
Coord PolyDef::exterior_box interface DIDGShapeDefinition
[propget] HRESULT OutsideWidth([out, retval] double *ret);
[propget] HRESULT OutsideHeight([out, retval] double *ret);
HRESULT SetOutside([in] double width,[in] double height);

(in) Minimum external width and height. Defaults to the graph's defaultsize attribute.

sides = integer int PolyDef::sides interface DIDGShapeDefinition
[propget] HRESULT Sides([out, retval] int *ret);
[propput] HRESULT Sides([in] int val);

(in) The number of sides of the polygon, when the shape is not "ellipse". Default: 4.

regular = true|false bool PolyDef::regular interface DIDGShapeDefinition
[propget] HRESULT Regular([out,retval] VARIANT_BOOL *ret);
[propput] HRESULT Regular([in] VARIANT_BOOL val);

(in) If true, specifies that the aspect ratio of the shape will be 1:1. (i.e. if the shape is an ellipse, it will be a circle, rectangle a square.) Default: false.

peripheries = integer int PolyDef::peripheries interface DIDGShapeDefinition
[propget] HRESULT Peripheries([out, retval] int *ret);
[propput] HRESULT Peripheries([in] int val);

(in) The number of extra borders to draw around the shape. Default: 0.

perispacing = float double PolyDef::perispacing interface DIDGShapeDefinition
[propget] HRESULT Spacing([out, retval] double *ret);
[propput] HRESULT Spacing([in] double val);

(in) The distance between the parallel lines of the peripheries. Because Dynagraph is coordinate-independent, the default value for this parameter is 0, so if you don't set this, you won't see the peripheries!

orientation = float double PolyDef::rotation interface DIDGShapeDefinition
[propget] HRESULT Rotation([out, retval] double *ret);
[propput] HRESULT Rotation([in] double val);

(in) The angle, in degrees, that the shape should be turned. By default, the rotation is 0, which means that the bottom line of a polygon is horizontal.

skew = float double PolyDef::skew interface DIDGShapeDefinition
[propget] HRESULT Skew([out, retval] double *ret);
[propput] HRESULT Skew([in] double val);

(in) The amount to tilt the shape. Default: 0.

distortion = float double PolyDef::distortion interface DIDGShapeDefinition
[propget] HRESULT Distortion([out, retval] double *ret);
[propput] HRESULT Distortion([in] double val);

(in) Make the top bigger than the bottom. Default: 0.

N/A NailType nail N/A

(in) Specifies the mobility of the node. Only Y-axis nailing is available, and only in Dynadag. Default: none.

DG_NONAIL The node can be positioned at the server's discretion.
DG_NAIL_X The server attempts to keep the node at the same X position.
DG_NAIL_Y The Y position (rank) is fixed.
DG_NAIL_BOTH The node is immobile.

Edge attributes

[ common attrs   ---    graph attrs   ---    node attrs ]
incrface attribute C++ class and field COM interface and method
minlen = real number double EdgeGeom::minLength interface IDGDrawnEdge
[propget] HRESULT Length([out,retval] double *pWidth);
[propput] HRESULT Length([in] double Width);

(in) The minimum length of the edge. In dynadag, this is multiplied by GraphGeom::separation.y to determine the verticle displacement between the nodes at either end of this edge. Default: 1.0.

N/A bool EdgeGeom::constraint interface IDGDrawnEdge
[propget] HRESULT Constraint([out, retval] VARIANT_BOOL *pConstraint);
[propput] HRESULT Constraint([in] VARIANT_BOOL Constraint);

(in,out) In dynadag, if this flag is set to true, the edge will always point downward. If this flag is set to false, the edge can point upward when there is a cycle in the graph. Dynadag will set constraint==false if it finds a cycle while inserting the edge.

backward=true|false bool EdgeGeom::backward N/A

If set, the Y constraints on the edge will be reversed, resulting in the edge being drawn in the opposite direction to other edges. This attribute affects cycle detection: if a cycle in the input graph contains at least one backward edge, then DynaDAG will not have to reverse one of the edges in order to generate a legal layout. (On the other hand, if all the edges in a cycle are marked "backward", then DynaDAG will need to unreverse one of them in order to generate layout.)

emphasizeflow=true|false bool EdgeGeom::s_edge N/A

If set and this edge is reversed (pointing against the "flow" of the rest of the graph due to cycles or the backward attribute), the edge will be drawn leaving the tail node and entering the head node in the direction of flow, resulting in an "S-shaped" (although more likely "C-shaped") backedge.

In order for this feature to work, the superengines kludge must be enabled. The easiest way to to this is to set [superengines=shapegen] on opening the graph.

N/A Port EdgeGeom::tailPort,headPort; interface IDGDrawnEdge
[propget] HRESULT TailPos([out,retval] POINTD *ppos);
[propput] HRESULT TailPos([in] POINTD tpos);
[propget] HRESULT HeadPos([out,retval] POINTD *ppos);
[propput] HRESULT HeadPos([in] POINTD pos);

Offsets of the ends of the edge from the tail and head node positions.

N/A bool tailClipped,headClipped N/A

Whether to clip this edge to the tail and head node regions.


Dynagraph on SourceForge