Open Baudin999 opened 4 years ago
Is there something I can do with the question to make it easier to help/answer? I'm really running against my own abilities and don't know how to continue...If there is anything I can do to make the question clearer, please let me know.
There is a project dot2svg inside of Msagl. Does it built on mac?
When I build the dot2svg project I get the following errors:
PS D:\Projects\automatic-graph-layout\GraphLayout\tools\Dot2Svg> dotnet build
Welcome to .NET Core 3.1!
---------------------
SDK Version: 3.1.300
Telemetry
---------
The .NET Core tools collect usage data in order to help us improve your experience. The data is anonymous. It is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.
Read more about .NET Core CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry
----------------
Explore documentation: https://aka.ms/dotnet-docs
Report issues and find source on GitHub: https://github.com/dotnet/core
Find out what's new: https://aka.ms/dotnet-whats-new
Learn about the installed HTTPS developer cert: https://aka.ms/aspnet-core-https
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli-docs
Write your first app: https://aka.ms/first-net-core-app
--------------------------------------------------------------------------------------
Microsoft (R) Build Engine version 16.6.0+5ff7b0c9e for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
Restored D:\Projects\automatic-graph-layout\GraphLayout\Drawing\AutomaticGraphLayout.Drawing.csproj (in 206 ms).
Restored D:\Projects\automatic-graph-layout\GraphLayout\MSAGL\AutomaticGraphLayout.csproj (in 206 ms).
AutomaticGraphLayout -> D:\Projects\automatic-graph-layout\GraphLayout\MSAGL\bin\Debug\netstandard2.0\AutomaticGraphLayout.dll
ArgsParser -> D:\Projects\automatic-graph-layout\GraphLayout\tools\ArgsParser\bin\Debug\ArgsParser.dll
AutomaticGraphLayout.Drawing -> D:\Projects\automatic-graph-layout\GraphLayout\Drawing\bin\Debug\netstandard2.0\AutomaticGraphLayout.Drawing.dll
C:\Program Files\dotnet\sdk\3.1.300\Microsoft.Common.CurrentVersion.targets(3032,5): error MSB3823: Non-string resources require the property GenerateResourceUsePreserializedResources to be set to true. [D:\Projects\automatic-graph-layout\GraphLayout\tools\GraphViewerGDI\GraphViewerGDI.csproj]
C:\Program Files\dotnet\sdk\3.1.300\Microsoft.Common.CurrentVersion.targets(3032,5): error MSB3822: Non-string resources require the System.Resources.Extensions assembly at runtime, but it was not found in this project's references. [D:\Projects\automatic-graph-layout\GraphLayout\tools\GraphViewerGDI\GraphViewerGDI.csproj]
C:\Program Files\dotnet\sdk\3.1.300\Microsoft.Common.CurrentVersion.targets(3032,5): error MSB3823: Non-string resources require the property GenerateResourceUsePreserializedResources to be set to true. [D:\Projects\automatic-graph-layout\GraphLayout\tools\GraphViewerGDI\GraphViewerGDI.csproj]
C:\Program Files\dotnet\sdk\3.1.300\Microsoft.Common.CurrentVersion.targets(3032,5): error MSB3822: Non-string resources require the System.Resources.Extensions assembly at runtime, but it was not found in this project's references. [D:\Projects\automatic-graph-layout\GraphLayout\tools\GraphViewerGDI\GraphViewerGDI.csproj]
Dot2Graph -> D:\Projects\automatic-graph-layout\GraphLayout\tools\Dot2Graph\bin\Debug\Dot2Graph.dll
Build FAILED.
C:\Program Files\dotnet\sdk\3.1.300\Microsoft.Common.CurrentVersion.targets(3032,5): error MSB3823: Non-string resources require the property GenerateResourceUsePreserializedResources to be set to true. [D:\Projects\automatic-graph-layout\GraphLayout\tools\GraphViewerGDI\GraphViewerGDI.csproj]
C:\Program Files\dotnet\sdk\3.1.300\Microsoft.Common.CurrentVersion.targets(3032,5): error MSB3822: Non-string resources require the System.Resources.Extensions assembly at runtime, but it was not found in this project's references. [D:\Projects\automatic-graph-layout\GraphLayout\tools\GraphViewerGDI\GraphViewerGDI.csproj]
C:\Program Files\dotnet\sdk\3.1.300\Microsoft.Common.CurrentVersion.targets(3032,5): error MSB3823: Non-string resources require the property GenerateResourceUsePreserializedResources to be set to true. [D:\Projects\automatic-graph-layout\GraphLayout\tools\GraphViewerGDI\GraphViewerGDI.csproj]
C:\Program Files\dotnet\sdk\3.1.300\Microsoft.Common.CurrentVersion.targets(3032,5): error MSB3822: Non-string resources require the System.Resources.Extensions assembly at runtime, but it was not found in this project's references. [D:\Projects\automatic-graph-layout\GraphLayout\tools\GraphViewerGDI\GraphViewerGDI.csproj]
0 Warning(s)
4 Error(s)
Time Elapsed 00:00:06.45
Following these steps do not seem to remove the issue: msbuild 4704
quick note: I've switched to Windows for this project, too frustrating to work on mac, but I still have the same limitations (cause eventually I'll need to compile on OSX) with dotnet core 3.1.
Is there something I can do to help this along? I don't mind putting in some time but I have no clue where to start...
It seems a relevant discussion https://github.com/microsoft/msbuild/issues/4704
Where in the library can I find the transformation from a GeometryGraph
to Svg? I keep bumping into position difficulties. There is a transformation needed plus the a flip to make it work but I haven't found it yet:
// Create a graph.
GeometryGraph graph = new GeometryGraph();
graph.UpdateBoundingBox();
graph.Nodes.Add(CreateNode("Bob"));
graph.Nodes.Add(CreateNode("Sally"));
graph.Nodes.Add(CreateNode("Rob"));
graph.Nodes.Add(CreateNode("Vincent"));
graph.Edges.Add(CreateEdge(graph.FindNodeByUserData("Bob"), graph.FindNodeByUserData("Sally")));
graph.Edges.Add(CreateEdge(graph.FindNodeByUserData("Sally"), graph.FindNodeByUserData("Vincent")));
graph.Edges.Add(CreateEdge(graph.FindNodeByUserData("Sally"), graph.FindNodeByUserData("Rob")));
var settings = new Microsoft.Msagl.Layout.Layered.SugiyamaLayoutSettings();
settings.EdgeRoutingSettings = new Microsoft.Msagl.Core.Routing.EdgeRoutingSettings
{
UseObstacleRectangles = true,
EdgeRoutingMode = Microsoft.Msagl.Core.Routing.EdgeRoutingMode.Spline
};
Microsoft.Msagl.Miscellaneous.LayoutHelpers.CalculateLayout(graph, settings, null);
// here be home-brew...
// render the root svg
var svg = new Svg
{
Height = graph.Height,
Width = graph.Width
};
foreach (var node in graph.Nodes)
{
// render the flow-chart sub-process
var subprocess = new Subprocess(node.UserData.ToString())
{
Height = node.Height,
Width = node.Width,
X = node.Center.X,
Y = node.Center.Y
};
svg.Children.Add(subprocess);
}
var stringSvg = svg.ToString();
Could you point me to a bit of relevant code to do the right rendering transformations?
Why don't you reuse the code from SvgGraphWriter?
I am trying but my biggest problem there is that it takes a Graph
and I have a GeometryGraph
and can't figure out how to transform the geometry object to the drawing object.
I did find something in Dot.cs
which seems to go the other way:
static void CreateGeometryGraph(Graph graph1)
{
var geomGraph = graph1.GeometryGraph = new GeometryGraph();
foreach (var n in graph1.Nodes)
geomGraph.Nodes.Add(n.GeometryNode);
foreach (var de in graph1.Edges)
{
var ge = de.GeometryEdge;
ge.Source = de.SourceNode.GeometryNode;
ge.Target = de.TargetNode.GeometryNode;
geomGraph.Edges.Add(de.GeometryEdge);
if (de.Label != null)
ge.Label = de.Label.GeometryLabel;
}
geomGraph.UpdateBoundingBox();
// geomGraph.Transform(GetTransformForDotSquashedGeometry());
}
The actual Shift reduce parser which parses the dotfile and generates the drawing graph is not in the source and so I can't find how the actual drawing graph is created.
I've seemed to inch into the right direction (@levnach thank you for the hints!) I have started with changing the SvgGraphWriter:
Constructor now changes the xmlWriterSettings to take a StringBuilder
so that I can output a string:
var xmlWriterSettings = new XmlWriterSettings { Indent = true };
xmlWriter = XmlWriter.Create(stringBuilder, xmlWriterSettings);
I've also flipped the implementation, I now start with a Graph
(the DrawingObject
) and create a GeometryGraph
from this:
private void CreateGeometryGraph(Graph graph)
{
var geometryGraph = graph.GeometryGraph = new GeometryGraph();
foreach (var n in graph.Nodes)
geometryGraph.Nodes.Add(n.GeometryNode);
foreach (var edge in graph.Edges)
{
if (edge.GeometryEdge is null)
{
edge.GeometryEdge = new Microsoft.Msagl.Core.Layout.Edge();
}
var gEdge = edge.GeometryEdge;
gEdge.Source = edge.SourceNode.GeometryNode;
gEdge.Target = edge.TargetNode.GeometryNode;
geometryGraph.Edges.Add(edge.GeometryEdge);
if (edge.Label != null)
gEdge.Label = edge.Label.GeometryLabel;
}
var settings = new SugiyamaLayoutSettings()
{
//
};
var lGraph = new LayeredLayout(geometryGraph, settings);
lGraph.Run();
geometryGraph.UpdateBoundingBox();
}
This outputs a correct graph, lot's of little things to tweak, for example:
but I seem to be inching closer.
If you don't mind I will leave this one open for a bit longer until 4704 is closed. After I've gotten it to work I'll write it up and submit it as documentation. Might help others.
hi @Baudin999 , did you ever work out the labels? I have been reading SvgWriter and I cant see why it would skip the edge or node labels.
No, it would not skip labels.
@levnach based on the code in https://github.com/microsoft/automatic-graph-layout/issues/248#issuecomment-663658274 , I see the labels on the nodes in code, but when the SVG is written I get the following verbatim, which seems to skip the label?:
<?xml version="1.0" encoding="utf-8"?>
<!--SvgWriter version 0.0.0.0-->
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="40" height="91.6875" id="svg2" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(20,591.6875)">
<!--Edges-->
<path fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" d="M 0 -561.6875 L 0 -540" />
<polygon stroke="#000000" stroke-opacity="1" stroke-width="1" fill="#000000" fill-opacity="1" points="-2.21694663167 -540 0 -530 2.21694663167 -540" />
<!--nodes-->
<ellipse fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" cx="0" cy="-520" rx="10" ry="10" />
<ellipse fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" cx="0" cy="-571.6875" rx="10" ry="10" />
<!--end of nodes-->
</g>
</svg>
It seems to be due to Width=0 on the label, so LabelIsValid returns false.
Setting width = 0.01 works, but the SvgWriter mispositions the labels. Fix is to add dominant-baseline="middle" text-anchor="middle" to the svg text attribute
Without attrs:
With new attrs:
@tick-rick, have you tried running dot2svg foo.dot, where dot2svg comes from GraphLayout\Tools? It sets the geometry correctly.
@levnach i tried compiling that but it didnt seem to compile on linux " Windows is required to build Windows desktop applications",
I was trying to avoid dot format as my current graph is from QuickGraph, and turning that into a string then into SVG seems taxing for bigger graphs. I will test out the webmsagl stuff to see if its a bit easier
I think I have this working as needed, my solution was to copy SvgGraphWriter and add the text anchoring.
FWIW, I noticed edge labels might not be correctly placed at https://github.com/microsoft/automatic-graph-layout/blob/master/GraphLayout/Drawing/SvgGraphWriter.cs#L252 as edge.Label.Center is empty (leading to y=0 in text node for edge), but label.GeometryLabel.Center is not, I fixed it by just checking if edge.Label.GeometryLabel is not null then using the geometry label for x,y respectively, else using x,y values from label.Center.
@tick-rick Thank you for the information, would it be possible to give a very small example solution with a dot2svg example? I con;t seem to get it to work properly.
I am still running into a wall when it comes to rendering a graph in SVG. Maybe a little context; I'm trying to recreate C4 diagrams using MSAGL instead of PlantUML.
I can't seem to get a grip on the API, the drawing part, the layout part, the SVG Writer part. Is there any documentation or some example project on getting simple graphs to render to SVG? Not write it to a file, but just the SVG string I can serve back up through my web endpoints, render it in an img
tag ?
I added a required sample: https://github.com/microsoft/automatic-graph-layout/commit/5c3e0ad3d4c741c5827b45c26b2c322c1ff9c32b But https://github.com/microsoft/automatic-graph-layout/issues/237#issuecomment-664065653 needs to be addressed.
@levnach it works, now I can try and get the graphs to look like I want. Thank you for the effort!
@levnach
I've started work on "rendering the SVG diagrams". My first steps resulted in this:
Is this something you might be interested in me sharing the code-base for? My goal is to recreate some of the functionality in PlantUML over to MSAGL.
@Baudin999 Sure, my code for rendering labels in SVG is not great. You seem to figured it out. Please share the relevant code, or maybe just submit a pull request to MSAGL. Thanks!
@levnach Would something like this work?
Example Project: ZDragon.Graphing
It's just a quick "sketch" of what I intend to do with the SvgRenderer. I can imagine this example is not in line with the vision of MSAGL. If this is something you'd be interested in adding to MSAGL I will try and create a pull request.
Just a note: Still missing a lot, like rendering subgraphs as container rectangles, setting padding....those basic things. My inspiration for the rendering comes from (and should eventually resemble): C4 PlantUml
@Baudin999 I think your code will be very useful for people using SVG output of MSAGL. So, yes, please go ahead with the pull request. Just a note that in the current state the output of the ZDragon.Graphing does not render the labels somehow. Only the edges are visible. Thank you!
@levnach
I've added the labels of the edges back in, but it has become a bit messy. Is there a way for me to clean it up before pushing a pull request?
There should be space around the labels of the Edges. I'll drill down a bit into the Sugiyama layout and see if I can find out how to render the example more like this:
My gut feeling is telling me that I should add the Edge labels as elements to the graph, but not sure if I'll be able to manage that by myself. I'm quite new when it comes to these types of algorithms.
GeometryGraph has exact positions for the labels. It is GeometryEdge.Label.Center. I wonder if it is possible to use them. @Baudin999, I modified WriteSvgSample, so the edge labels are rendered now.
@levnach Those centers help, but I'm still working on creating more space, really filling out the diagram so that it looks a bit better:
There is still not enough padding and can't figure out how to properly make this work.
For example:
I have a feeling that these points can be fixed using the settings, so I've been playing with the settings:
var routingSettings = new Microsoft.Msagl.Core.Routing.EdgeRoutingSettings {
UseObstacleRectangles = true,
BendPenalty = 100,
EdgeRoutingMode = Microsoft.Msagl.Core.Routing.EdgeRoutingMode.StraightLine
};
var settings = new SugiyamaLayoutSettings {
ClusterMargin = 50,
PackingAspectRatio = 3,
PackingMethod = Microsoft.Msagl.Core.Layout.PackingMethod.Columns,
RepetitionCoefficientForOrdering = 0,
EdgeRoutingSettings = routingSettings,
NodeSeparation = 50,
LayerSeparation = 150
};
None of these settings seem to really hit the sweetspot. I haven't been able to work out the issues if you could point me in the right direction I can make the example look pretty and do a merge request.
@Baudin999 , it is getting close to accepted quality. Why don't you create a pull request and I will try to improve the layout with some settings? When we are both happy with the result I will merge the request.
@levnach pull request created!
Hi, I'm rewriting this question because I think the original question was not clear enough. I am trying to create an SVG, but not render directly to file. I've found some snippets of code but not a clear way of achieving my goals.
First: I'm using .NET core on a mac
I am using this "tutorial" to get started, I would really appreciate being pointed to better alternatives.
I'm setting up my graph like this:
Now the question is, how do I get an SVG (or XElement or something along those lines) so I can embed this SVG. I Cannot write it to file some my attempts at
SvgGraphWriter.Write
have failed. I can't use the constructor because I can't pass in my graph and I can't create aGraphRenderer
beause I'm using dotnet core.Any help would be much appreciated.