Git Product home page Git Product logo

rubjerg / graphviz.netwrapper Goto Github PK

View Code? Open in Web Editor NEW
36.0 36.0 16.0 13.15 MB

Lean .NET wrapper around Graphviz for building graphs, reading/writing dot files, exporting images, or programmatically reading out the layout attributes.

License: Eclipse Public License 2.0

C++ 7.36% C 33.33% C# 59.10% Batchfile 0.04% Shell 0.17%
csharp dotnet graph graphdrawing graphviz visualization

graphviz.netwrapper's People

Contributors

chivandikwa avatar chtenb avatar manuelesvi avatar modery avatar peitschie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

graphviz.netwrapper's Issues

Support unicode

Currently we marshal strings as ANSI strings, but I would like to support unicode in e.g. label strings.
Relevant links:

Graphviz doesn't seem to support utf16, while PtrToStringUni is utf16.
PtrToStringUTF8 is not available on .NET 4.8.

Can't add an edge to a port - API only seems to support Nodes

Graphviz supports drawing an edge from a Node to a Port, e.g. this Fiddle

(DOT file contents below in case the Fiddle doesn't work)

digraph Graph1 {
   node [fontname=Helvetica,
   	shape=box,
   	style=filled,
   	fillcolor=lemonchiffon  
   ];
   edge [color=red,
   	fontname=Helvetica
   ];
   Node1	[label=<<table border="0"><tr><td>Node1</td></tr><tr><td port="port1" border="1">Port1</td></tr></table>>];
   Node2 -> Node1:port1;
}

So it's valid to target the edge at the port using the reference "Node1:port1".

I'm trying to achieve this using Graphviz.NetWrapper. What I'm finding is that RootGraph.GetNode("Node1:port1") doesn't work, and if I use RootGraph.GetNode("Node1") then I can't find anything in the API that will let me specify the portname when I try to use RootGraph.GetOrAddEdge()

 public class DemonstratePortIssue
  {
      private const string OutputFolder = "Diagrams";

      public void GenerateDiagram()
      {
          var graphName = "Graph1";
          RootGraph root = CommonDiagramUtils.GenerateNewRootGraph(graphName);

          var node1 = root.GetOrAddNode("Node1");
          node1.SetAttributeHtml("label", "<table border=\"0\"><tr><td>Node1</td></tr><tr><td port=\"port1\" border=\"1\">Port1</td></tr></table>");
          var node2 = root.GetOrAddNode("Node2");

          //var port = root.GetNode("port1");
          var port = root.GetOrAddNode("Node1:port1");
          root.GetOrAddEdge(node2, port, "edge1");

          GenerateOutputFiles("DemonstratePortIssue", root);
      }

      private void GenerateOutputFiles(string graphName, RootGraph root)
      {
          // Make sure output folder exists
          var baseFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, OutputFolder);
          Directory.CreateDirectory(OutputFolder);

          root.ToDotFile(Path.Combine(baseFolder, $"{graphName}.dot"));
          root.ToSvgFile(Path.Combine(baseFolder, $"{graphName}.svg"), "fdp");

      }
  }

I'm thinking it might need an optional "portName" parameter on GetOrAddEdge, if it's non-null then append it to the target node ref, separated with a colon?

Support different coordinate systems

Graphviz has a bottomleft origin, but many applications require a topleft origin. It would be nice if you could configure this and the coordinates were transformed correspondingly.

Changing project order in solution makes the build fail

#33 reproduces the issue.

This problems only occurs when executing MSBuild Rubjerg.Graphviz.sln from the commandline (Developer Command Prompt for VS 2019).
From within Visual Studio the build always succeeds.
MSBuild version is the newest: 16.8.3.61104

Update main.yml

Actions issues two warnings about things being outdated:

Unable to add non HTML label starting surrounded with `<` and `>`

De AddLabel method performs a check on the first and last character of the value and decides based on that whether it is a HTML string or not. However, this makes it unable to express that you want a literal string starting and ending with <,>. Therefore we need to add separate methods for adding string literals and HTML literals.

@chivandikwa I'm mentioning you for completeness sake, since you provided the current code.

Linux Support

I am curious if there has been any attempt at getting a Linux compatible version? I have a fork of this repo where I am able to compile against netcoreapp3.1-windows just fine. However, since the Graphviz native libraries are windows specific I can't just use it on Linux. I am using the library from an Azure app service and it would be a lot cheaper if it could run on a Linux app service plan.

I spent a day diving into the C++ project to see what it might take to get a Linux version compiling. After that initial effort I thought it might be worth asking if you have already given this subject any thought and just haven't had time to do the work. If you do already have some ideas on the path forward here I would be willing to help progress Linux support if I can. As a disclaimer I am predominately a Windows C# developer myself, so I don't bring any significant C++ or Linux expertise, but this is an area of interest for me.

Switch off using System.Drawing

  • It's based on float, which means we loose accuracy
  • It's tied to topleft coordinate system, which means we're currently misusing it.
  • To decide whether we should keep using the Color type

Update graphviz version

Update to the next official release, whenevere that comes out. That would also be a good moment to release a new version of this wrapper.

Can't create SVG/PNG with space in folder path

I just tried to upgrade my project to .net8 and Graphviz.NetWrapper 2.0.0. After making a few smaller changes to make my code compatible with the new version, I still ran into some issues when trying to save my Graph as a SVG or PNG. I then tried a small proof of concept app, and noticed that I only get an error if my folder path contains a space.

Here's my sample code:

using Rubjerg.Graphviz;

class Program
{
    static void Main(string[] args)
    {
        RootGraph root = RootGraph.CreateNew(GraphType.Directed, "Some Unique Identifier");
        Node nodeA = root.GetOrAddNode("A");
        Node nodeB = root.GetOrAddNode("B");
        Node nodeC = root.GetOrAddNode("C");
        Edge edgeAB = root.GetOrAddEdge(nodeA, nodeB, "Some edge name");
        Edge edgeBC = root.GetOrAddEdge(nodeB, nodeC, "Some edge name");
        Edge anotherEdgeBC = root.GetOrAddEdge(nodeB, nodeC, "Another edge name");
        Edge edgeAB1 = root.GetOrAddEdge(nodeA, nodeB);
        Edge edgeAB2 = root.GetOrAddEdge(nodeA, nodeB);
        Node.IntroduceAttribute(root, "my attribute", "defaultvalue");
        nodeA.SetAttribute("my attribute", "othervalue");
        Edge.IntroduceAttribute(root, "my attribute", "defaultvalue");
        edgeAB.SetAttribute("my attribute", "othervalue");
        edgeBC.SafeSetAttribute("arrowsize", "2.0", "1.0");
        edgeBC.SetAttribute("new attr", "value");
        Node.IntroduceAttribute(root, "label", "defaultlabel");
        nodeB.SetAttributeHtml("label", "<b>Some HTML string</b>");

        // We can simply export this graph to a text file in dot format
        root.ToDotFile(@"c:/tmp/Test Folder/out.dot");

        RootGraph root2 = RootGraph.FromDotFile("c:/tmp/Test Folder/out.dot");

        //the following 2 lines fail
        root2.ToSvgFile("c:/tmp/Test Folder/dot_out.svg");
        root2.ToPngFile("c:/tmp/Test Folder/dot_out.png");

    }
}

This is the error I get:

An unhandled exception of type 'System.ApplicationException' occurred in Rubjerg.Graphviz.dll: 'Process exited with code 2. Error details: Error: dot: can't open Folder/dot_out.svg: No such file or directory'

If I change it to "c:/tmp/TestFolder/dot_out.svg" it works.

Unable to use html in node label

On setting node label to html via SetAttribute call with something like "<sample>" the result is rendered as raw text.

How can I achieve this?

Generation bug

Given this DOT graph:

digraph {
compound=true;
node [shape=Mrecord]
rankdir="LR"

subgraph "clusterOpen"
	{
	label = "Open"
"Assigned" [label="Assigned|exit / OnDeassigned"];
}
"Deferred" [label="Deferred|entry / Function"];
"Closed" [label="Closed"];

"Open" -> "Assigned" [style="solid", label="Assign / OnAssigned"];
"Assigned" -> "Assigned" [style="solid", label="Assign"];
"Assigned" -> "Closed" [style="solid", label="Close"];
"Assigned" -> "Deferred" [style="solid", label="Defer"];
"Deferred" -> "Assigned" [style="solid", label="Assign / OnAssigned"];
 init [label="", shape=point];
 init -> "Open"[style = "solid"]
}

Graphiviz generates this diagram:
image

Using this code:

	var root = RootGraph.FromDotString(bug.ToDotGraph());
	root.ComputeLayout();
	root.ToSvgFile(@"c:\temp\diagram.svg");

It generates this diagram:
image

The Open text is missing.

Fix flaky test TestRecordShapeAlignment

The test TestRecordShapeAlignment fails on the github test server, but passes locally. Figure out why.
For some reason calling dot.exe directly on dot files does not give a wrong alignment on the github server.

File generation in 2.0.0 in a Windows Forms app much slower

I noticed that version 2.0.0 is significantly slower in file generation (ToDotFile, ToSvgFile, for example) than 1.1.0 when used in a Windows Forms application. Every single ToXYZFile call seems to open a separate console window for a second, I assume to generate the file. This did not happen in 1.1.0

The code example (which generates 20 files) below takes less than a second overall with version 1.1.0. For 2.0.0, it takes a bit more than 20 seconds.
For some of my actual use cases in my application, I noticed that instead of 18 seconds it takes 2 minutes to complete.

Here's how to replicate it:

  1. Create a new VSCode project. Use dotnet new winforms to initialize a new simple Windows Forms app
  2. update the csproj file to reference the Nuget package (either 1.1.0 or 2.0.0):
  <ItemGroup>
    <PackageReference Include="Rubjerg.Graphviz" Version="1.1.0" />
  </ItemGroup>
  1. Update the Form1.cs file to include the following code right after InitializeComponent();

1.1.0:

        Console.WriteLine("Starting: " + DateTime.Now);
        for (int i = 0; i < 10; i++)
        {

            RootGraph root = RootGraph.CreateNew("",GraphType.Directed);
            Node nodeA = root.GetOrAddNode("A");
            root.ComputeLayout();
            root.ToDotFile("c:/tmp/out" + i + ".dot");
            RootGraph root2 = RootGraph.FromDotFile("c:/tmp/out" + i + ".dot");
            root2.ComputeLayout();
            root2.ToSvgFile("c:/tmp/dot_out" + i + ".svg");
        }
        Console.WriteLine("Finished: " + DateTime.Now);

2.0.0:

        Console.WriteLine("Starting: " + DateTime.Now);
        for (int i = 0; i < 10; i++)
        {

            RootGraph root = RootGraph.CreateNew(GraphType.Directed, "");
            Node nodeA = root.GetOrAddNode("A");
            root.CreateLayout();
            root.ToDotFile("c:/tmp/out" + i + ".dot");
            RootGraph root2 = RootGraph.FromDotFile("c:/tmp/out" + i + ".dot");
            root2.CreateLayout();
            root2.ToSvgFile("c:/tmp/dot_out" + i + ".svg");
        }
        Console.WriteLine("Finished: " + DateTime.Now);
    }

Assembly.GetExecutingAssembly().Location is empty for self-contained (single file) apps

I'm using this library in a self-contained .NET application. During development, everything was working well, but once I published a package I got the following error:
image

The following code is the "culprit" here:
string exeDirectory = AppDomain.CurrentDomain.RelativeSearchPath ?? Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
https://github.com/Rubjerg/Graphviz.NetWrapper/blob/master/Rubjerg.Graphviz/GraphvizCommand.cs#L51

The problem is that Assembly.GetExecutingAssembly().Location is empty for single file apps, thus the Path.Combine call right after the above code fails.

Using System.AppContext.BaseDirectory as an additional option should work from what I understand, so string exeDirectory = AppDomain.CurrentDomain.RelativeSearchPath ?? Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Path.GetDirectoryName(System.AppContext.BaseDirectory);
might be the right way to fix this issue

Change dot rendering to be done out-of-process

Right now this is done in ComputeLayout though interop calls, but experience has shown that this is prone to uprooting lingering issues in GraphViz. A more robust approach would probably be to invoke dot.exe in a separate process, and communicate dot/xdot via stdin/stdout.

.NET 6 tests give warnings on the stderr

.NET Framework 4.8 tests run without any warnings showing.
Example:

Warning: Could not load "D:\a\Graphviz.NetWrapper\Graphviz.NetWrapper\Rubjerg.Graphviz.Test\bin\x64\Release\net6.0\gvplugin_pango.dll" - It was found, so perhaps one of its dependents was not.  Try ldd.
Warning: dummynode-2 -> dummynode-3: tail is inside head cluster cluster_1
Warning: dummynode-2 -> dummynode-3: head is inside tail cluster cluster_1
Warning: no hard-coded metrics for 'Tahoma'.  Falling back to 'Times' metrics
Warning: node N, port >|< unrecognized

Is this cause by the .NET Framework tests not redirecting stderr properly, or are these warnings actually only occuring on .NET 6.0?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.