2011-12-13 18 views
5

Buduję plik .dot reprezentujący skierowany wykres acykliczny.Utwórz obraz z pliku .dot w języku C#

Potrzebuję wygenerować obraz z tego pliku graph.dot (przy użyciu C#), dzięki czemu mogę wyświetlić obraz w ramce Picture Box w mojej aplikacji. Jakiej biblioteki mam użyć?

Używając polecenia Graphviz w wierszu poleceń:

dot -Tpng graph.dot -o graph.png 

jestem w stanie generować grzywny obrazu, więc wiem, że formatowanie mojego pliku .dot jest poprawna.

Dziękuję.

+0

Zakładam więc, że nie chcesz uruchamiać narzędzia dot z aplikacji C#? – RQDQ

+0

Nie, to nie jest to, czego chcę. – Rachel

Odpowiedz

4

Dziękuję @ marapet za skierowanie mnie do projektu Davida Browna.

Pobrałem próbki w: David Brown's Implicit Operator

Próbka działa dobrze.

Skopiowałem wymagany kod do mojego projektu. Musiałem zmienić mój .NET Target Framework z 4.0 na 3.5, ale to nie jest problem.

Do tej pory kod nigdy się nie zawiesił. (Nawet jeśli inni ludzie zgłaszali problemy.)

UPDATE

strona David Brown wydaje się być w dół, więc zaktualizowaliśmy tę odpowiedź z kodem ja pobranej ze strony internetowej.

//Code for this Class downloaded from http://implicitoperator.com/blog/2010/4/11/graphviz-c-sample.html 

public class GraphViz 
{ 

    public const string LIB_GVC = "gvc.dll"; 
    public const string LIB_GRAPH = "graph.dll"; 
    public const int SUCCESS = 0; 

    /// <summary> 
    /// Creates a new Graphviz context. 
    /// </summary> 
    [DllImport(LIB_GVC)] 
    public static extern IntPtr gvContext(); 

    /// <summary> 
    /// Reads a graph from a string. 
    /// </summary> 
    [DllImport(LIB_GRAPH)] 
    public static extern IntPtr agmemread(string data); 

    /// <summary> 
    /// Renders a graph in memory. 
    /// </summary> 
    [DllImport(LIB_GVC)] 
    public static extern int gvRenderData(IntPtr gvc, IntPtr g, 
     string format, out IntPtr result, out int length); 

    /// <summary> 
    /// Applies a layout to a graph using the given engine. 
    /// </summary> 
    [DllImport(LIB_GVC)] 
    public static extern int gvLayout(IntPtr gvc, IntPtr g, string engine); 

    /// <summary> 
    /// Releases the resources used by a layout. 
    /// </summary> 
    [DllImport(LIB_GVC)] 
    public static extern int gvFreeLayout(IntPtr gvc, IntPtr g); 

    /// <summary> 
    /// Releases a context's resources. 
    /// </summary> 
    [DllImport(LIB_GVC)] 
    public static extern int gvFreeContext(IntPtr gvc); 

    /// <summary> 
    /// Releases the resources used by a graph. 
    /// </summary> 
    [DllImport(LIB_GRAPH)] 
    public static extern void agclose(IntPtr g); 

    public static Image RenderImage(string source, string layout, string format) 
    { 
     // Create a Graphviz context 
     IntPtr gvc = gvContext(); 
     if (gvc == IntPtr.Zero) 
      throw new Exception("Failed to create Graphviz context."); 

     // Load the DOT data into a graph 
     IntPtr g = agmemread(source); 
     if (g == IntPtr.Zero) 
      throw new Exception("Failed to create graph from source. Check for syntax errors."); 

     // Apply a layout 
     if (gvLayout(gvc, g, layout) != SUCCESS) 
      throw new Exception("Layout failed."); 

     IntPtr result; 
     int length; 

     // Render the graph 
     if (gvRenderData(gvc, g, format, out result, out length) != SUCCESS) 
      throw new Exception("Render failed."); 

     // Create an array to hold the rendered graph 
     byte[] bytes = new byte[length]; 

     // Copy the image from the IntPtr 
     Marshal.Copy(result, bytes, 0, length); 

     // Free up the resources 
     gvFreeLayout(gvc, g); 
     agclose(g); 
     gvFreeContext(gvc); 

     using (MemoryStream stream = new MemoryStream(bytes)) 
     { 
      return Image.FromStream(stream); 
     } 
    } 
} 
+0

To świetnie!Czy mógłbyś podzielić się z kimś wersją OS i wersją grafviz, z której korzystasz? – marapet

+1

@marapet używam Windows 7 Professional 64-bit z SP1. Wersja GraphViz to 2.28.0, pobrana z http://www.graphviz.org/Download_windows.php. Kod nadal nie uległ awarii :) – Rachel

+0

Hej, czy nadal masz próbkę? Strona nie działa i muszę spojrzeć na ten kod. – pmichna

2

Można użyć, aby rozpocząć proces dot.exe

ProcessStartInfo startInfo = new ProcessStartInfo("dot.exe"); 
startInfo.Arguments = "-Tpng graph.dot -o graph.png"; 

Process.Start(startInfo); 
+0

Dziękuję za twój wkład. To działa, ale nie tego szukam. Wolałbym, gdybym mógł użyć jakiejś biblioteki, która ma metodę, która pobiera plik .dot jako parametr (lub String znaleziony w pliku) i zwraca obraz. – Rachel

+0

@Rachel bez problemu, trochę krówki, ale wszystko, co mogłem wymyślić. –

+0

+1 Tak, to hack. Ale czasami taki hak może wydostać cię z więzów. – user

2

Trudna jest ta jedna, znalazłem otoki NET Graphviz nazywa GrapVizNet który może sprawia, że ​​to możliwe.

Bardziej interesujący jest tworzenie opakowania z numerem PInvoke. Wierzę, że this jest dokładnie tym, czego potrzebujesz. Nie jest to najbardziej eleganckie rozwiązanie, ale może jedyne, co masz.

+2

Projekt Davida Browna rzeczywiście dokładnie odpowiada na pytanie. Jedyny problem polega na tym, że wydaje się, że w ostatnich wersjach pojawił się błąd - zobacz także pytanie Davida Browna na temat: http://stackoverflow.com/a/4876966/63733 – marapet

+0

@marapet +1 za obejrzenie tego. Szybkie wyszukiwanie nie daje mi żadnych informacji, czy ten błąd został naprawiony. Musisz to wypróbować, aby się przekonać. –

+0

Nie ma - przynajmniej nie zgodnie ze statusem raportów o błędach ([1870] (http://www.graphviz.org/bugs/b1870.html) i [1775] (http: //www.graphviz .org/bugs/b1775.html)) złożony przez @ Davida Browna. Ktoś sugeruje, że sam tworzy sam graphviz na Windowsie z tym samym kompilatorem - nie wiem, czy to pomaga. – marapet