2011-12-13 21 views
5

Sto costruendo un file .dot per rappresentare un grafico aciclico diretto.Crea immagine da file .dot in C#

Ho bisogno di generare un'immagine da questo file graph.dot (usando C#) in modo che possa mostrare l'immagine in una Picture Box nella mia applicazione. Quale libreria dovrei usare?

Utilizzando il comando di GraphViz nel prompt dei comandi:

dot -Tpng graph.dot -o graph.png 

io sono in grado di generare la bella immagine, quindi so che la formattazione del mio file dot è corretto.

Grazie.

+0

Quindi presumo che tu non voglia solo eseguire l'utilità punto dall'applicazione C#? – RQDQ

+0

No, non è quello che voglio. – Rachel

risposta

4

Grazie @marapet per avermi segnalato il progetto di David Brown.

Ho scaricato il campione a: David Brown's Implicit Operator

L'esempio funziona bene.

Ho copiato il codice richiesto nel mio progetto. Ho dovuto cambiare il mio .NET Framework Target dalla 4.0 alla 3.5, ma questo non è un problema.

Finora, il codice non si è mai arrestato. (Anche se altre persone hanno riportato problemi.)

UPDATE

il sito web di David Brown sembra essere giù così ho aggiornato questa risposta con il codice che avevo preso dal sito web.

//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

È grandioso!Ti dispiacerebbe condividere quale versione di OS e Graphviz stai usando? – marapet

+1

@marapet Sto usando Windows 7 Professional a 64 bit con SP1. La versione GraphViz è 2.28.0, come scaricata da http://www.graphviz.org/Download_windows.php. Il codice non si è ancora arrestato :) – Rachel

+0

Ehi, hai ancora il campione? Il sito web è inattivo e ho bisogno di guardare quel codice. – pmichna

2

Si potrebbe utilizzare Process per avviare dot.exe

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

Process.Start(startInfo); 
+0

Grazie per l'input. Funziona, ma non è quello che sto cercando. Preferirei se potessi usare qualche libreria che ha un metodo che prende il file .dot come parametro (o la stringa trovata nel file) e restituisce l'immagine. – Rachel

+0

@Rachel nessun problema, un po 'di caramelle ma tutto ciò a cui riuscivo a pensare. –

+0

+1 Sì, è un hack. Ma a volte un attacco come questo può farti uscire da un legame. – user

2

Questo è un duro, ho trovato un wrapper NET per GraphViz chiamato GrapVizNet che rende forse è possibile.

Uno più interessante è quello di creare un wrapper con PInvoke. Credo che this sia esattamente quello di cui hai bisogno. Non la soluzione più elegante ma forse l'unica che hai.

+2

Il progetto di David Brown fa esattamente esattamente ciò che viene chiesto nella domanda. L'unico problema è che sembra esserci un bug nelle versioni recenti - vedi anche la domanda di David Brown su SO: http://stackoverflow.com/a/4876966/63733 – marapet

+0

@marapet +1 per averlo visto. Una ricerca rapida non mi dà alcuna informazione se questo bug è stato corretto. Dovrai provarlo per scoprirlo. –

+0

Non ha - almeno non in base allo stato delle segnalazioni di bug ([1870] (http://www.graphviz.org/bugs/b1870.html) e [1775] (http: //www.graphviz .org/bugs/b1775.html) archiviata da @ David Brown. Qualcuno suggerisce di costruire graphviz su Windows con lo stesso compilatore - non so se questo aiuti. – marapet