Graphviz

Graphviz is a graph visualization software.

History

Graphvis was created by AT&T and released under the Eclipse Public License. It interpretes the [DOT Language](https://en.wikipedia.org/wiki/DOT_(graph_description_language), that describes graphs (nodes and edges).

FAQ

What is it?

Tools that transform a DOT syntax into a graphical output (svg, png, jpg, ..)

How cool is it?

Very.

Competitors?

msagl, Mathematica, vis.js

Where is it?

https://www.graphviz.org

When to use it?

When you can describe your graph in a clean way, and want to process it into a standard image.

Is it dead?

Nope, There is some activity every few month and a nice mailing list.

How to use it

Init

Graphviz is a very big and complex beast, this example shows just the bare minimum to generate a svg output.

file: download.sh

#!/bin/bash

wget https://graphviz.gitlab.io/pub/graphviz/stable/SOURCES/graphviz.tar.gz
tar -xaf graphviz.tar.gz
cd graphviz-2.40.1
./configure \
    --enable-static --disable-shared \
    --with-rsvg \
    --disable-ltdl \
    --without-libgd \
    --without-freetype2 \
    --without-fontconfig \
    --without-x \
    --without-expat \
    --without-devil \
    --without-webp \
    --without-poppler \
    --without-ghostscript \
    --without-visio \
    --without-pangocairo \
    --without-lasi \
    --without-glitz \
    --without-gdk \
    --without-gdk-pixbuf \
    --without-gtk \
    --without-gtkgl \
    --without-gtkglext \
    --without-gts \
    --without-ann \
    --without-glade \
    --without-ming \
    --without-qt \
    --without-quartz \
    --without-gdiplus \
    --without-glut \
    --without-sfdp \
    --without-smyrna \
    --without-ortho \
    --without-dgcola \
    --without-digcola \
    --without-ipseccola \
    --enable-swig=no \
    --enable-sharp=no \
    --enable-go=no \
    --enable-guile=no \
    --enable-io=no \
    --enable-java=no \
    --enable-lua=no \
    --enable-ocaml=no \
    --enable-perl=no \
    --enable-php=no \
    --enable-python=no \
    --enable-python23=no \
    --enable-python24=no \
    --enable-python25=no \
    --enable-python26=no \
    --enable-python27=no \
    --enable-python34=no \
    --enable-r=no \
    --enable-ruby=no \
    --enable-tcl=no
make

To process a dot string into a svg string, we just need a few lines of code.

file: main.c

#include <stdio.h>

#include <gvc.h>
#include <gvplugin.h>

extern gvplugin_library_t gvplugin_dot_layout_LTX_library;
extern gvplugin_library_t gvplugin_core_LTX_library;

lt_symlist_t lt_preloaded_symbols[] = {
	{ "gvplugin_dot_layout_LTX_library", (void*)(&gvplugin_dot_layout_LTX_library) },
	{ "gvplugin_core_LTX_library", (void*)(&gvplugin_core_LTX_library) },
	{ 0, 0 }
};

void cleanup_svg(char * buff, size_t buff_size) {
	gvFreeRenderData(buff);
	buff = NULL;
	buff_size = 0;
}

void create_svg_from_dot(const char *cp, char ** buff, unsigned int* buff_size) {
	Agraph_t *g;
	GVC_t *gvc = gvContextPlugins(lt_preloaded_symbols, 0);
	g = agmemread(cp);
	gvLayout(gvc, g, "dot");
	gvRenderData(gvc, g, "svg", buff, buff_size);
	gvFinalize(gvc);
	gvFreeLayout(gvc, g);
	gvFreeContext(gvc);
	agclose(g);

}


int main(int argc, char **argv) {
	const char * cp = "digraph etete { a -> {b, c}; c-> {d, e};}";
	char * buff;
	size_t buff_size;

	create_svg_from_dot(cp, &buff, &buff_size);
	printf("%s", buff);
	cleanup_svg(buff, buff_size);

	return 0;
}

Compiling is a rather straigt forward:

file: compile_and_run.sh

#!/bin/bash

clang \
	-c \
	-omain.o \
	-O3 -Wall -Wextra \
	-Wno-unused-parameter \
	-Igraphviz-2.40.1/lib/gvc/ \
	-Igraphviz-2.40.1/lib/common \
	-Igraphviz-2.40.1/lib/pathplan \
	-Igraphviz-2.40.1/lib/cgraph \
	-Igraphviz-2.40.1/lib/cdt \
	main.c 
clang \
	-omain \
	-O3 \
	-Lgraphviz-2.40.1/lib/gvc/.libs/ \
	-Lgraphviz-2.40.1/lib/cgraph/.libs/ \
	-Lgraphviz-2.40.1/lib/cdt/.libs/ \
	-Lgraphviz-2.40.1/lib/pathplan/.libs/ \
	-Lgraphviz-2.40.1/plugin/core/.libs/ \
	-Lgraphviz-2.40.1/plugin/dot_layout/.libs/ \
	main.o \
	-Wl,--start-group \
		-lcdt \
		-lcgraph \
		-lgvc \
		-lpathplan \
		-lgvplugin_core \
		-lgvplugin_dot_layout \
	-Wl,--end-group \
	-lm -lz

./main 
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
 -->
<!-- Title: etete Pages: 1 -->
<svg width="170pt" height="188pt"
 viewBox="0.00 0.00 170.00 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<title>etete</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-184 166,-184 166,4 -4,4"/>
<!-- a -->
<g id="node1" class="node">
<title>a</title>
<ellipse fill="none" stroke="#000000" cx="63" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">a</text>
</g>
<!-- b -->
<g id="node2" class="node">
<title>b</title>
<ellipse fill="none" stroke="#000000" cx="27" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">b</text>
</g>
<!-- a&#45;&gt;b -->
<g id="edge1" class="edge">
<title>a&#45;&gt;b</title>
<path fill="none" stroke="#000000" d="M54.2854,-144.5708C50.0403,-136.0807 44.8464,-125.6929 40.1337,-116.2674"/>
<polygon fill="#000000" stroke="#000000" points="43.237,-114.6477 35.6343,-107.2687 36.976,-117.7782 43.237,-114.6477"/>
</g>
<!-- c -->
<g id="node3" class="node">
<title>c</title>
<ellipse fill="none" stroke="#000000" cx="99" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">c</text>
</g>
<!-- a&#45;&gt;c -->
<g id="edge2" class="edge">
<title>a&#45;&gt;c</title>
<path fill="none" stroke="#000000" d="M71.7146,-144.5708C75.9597,-136.0807 81.1536,-125.6929 85.8663,-116.2674"/>
<polygon fill="#000000" stroke="#000000" points="89.024,-117.7782 90.3657,-107.2687 82.763,-114.6477 89.024,-117.7782"/>
</g>
<!-- d -->
<g id="node4" class="node">
<title>d</title>
<ellipse fill="none" stroke="#000000" cx="63" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">d</text>
</g>
<!-- c&#45;&gt;d -->
<g id="edge3" class="edge">
<title>c&#45;&gt;d</title>
<path fill="none" stroke="#000000" d="M90.2854,-72.5708C86.0403,-64.0807 80.8464,-53.6929 76.1337,-44.2674"/>
<polygon fill="#000000" stroke="#000000" points="79.237,-42.6477 71.6343,-35.2687 72.976,-45.7782 79.237,-42.6477"/>
</g>
<!-- e -->
<g id="node5" class="node">
<title>e</title>
<ellipse fill="none" stroke="#000000" cx="135" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="135" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">e</text>
</g>
<!-- c&#45;&gt;e -->
<g id="edge4" class="edge">
<title>c&#45;&gt;e</title>
<path fill="none" stroke="#000000" d="M107.7146,-72.5708C111.9597,-64.0807 117.1536,-53.6929 121.8663,-44.2674"/>
<polygon fill="#000000" stroke="#000000" points="125.024,-45.7782 126.3657,-35.2687 118.763,-42.6477 125.024,-45.7782"/>
</g>
</g>
</svg>

Further reading:

We only tipped the top of the iceberg here. There is much more: