microsoft / automatic-graph-layout

A set of tools for graph layout and viewing
Other
1.35k stars 302 forks source link

Drawing boxes at the background #288

Closed NiklasVJM closed 3 years ago

NiklasVJM commented 3 years ago

Hi!

First of all, thank you for this wonderful tool!

I was thinking, is it possible to draw stuff at the background of the canvas in a way, that it does not effect the routing algorithms? Attached is a picture. So in this picture, I would like to draw these red boxes in specific places (with X1, X2 and Y1 and Y2 coordinates) and these boxes are at the background, but should not affect the routing algorithms in any way. So for the tool, it is like they don't exists. In this case, simple image is not possible, unfortunately.

Is this possible?

A small code example would be awesome!

Screenshot 2021-07-12 152008

lafrank commented 3 years ago

You can look into my repository https://github.com/lafrank/automatic-graph-layout in which I implemented AnnotationObjects for the same purpose. In my implementation annotation objects form a distinct collection and are unrelated to the graph objects. They are simply drawn in the background or foreground of the graph as required, may be clicked, dragged, etc. Implementation is only for GDIViewer, hence WinForms. Example graph :

[image: image.png]

Considering code, look for GViewer Annotation object related methods and properties, they are quite self explanatory.

NiklasVJM commented 3 years ago

Hi!

Thank you for your answer!

Does it include this labeling, as seen in the picture ("FIRST BOX" etc.)?

I was browsing trough your github-page, but couldn't find code example right away. Do you have direct link? Your picture is not showing, but I assume it is exactly what I'm needing. So sorry about these questions, still quite new programmer :)

lafrank commented 3 years ago

I added the screenshot as attachment, hope it'll show up now. I unfortunately don't have a ready-to-view code example because the whole project using the code is in a private repository. But in case you are interested based on the screenshot I can gather some code to build a simple demo app.

image

NiklasVJM commented 3 years ago

Hi!

Thank you for your reply!

Yes, I would be very interested to have a little sample data to act as a guide. Right now, I have something like this:

        `private void ConnectionsDialogGraph_Loaded(object sender, RoutedEventArgs e)
       {
        var gviewer = new GViewer();
        var form = CreateOrAttachForm(gviewer, null);
        gviewer.NeedToCalculateLayout = false;
        Graph graph = new Graph();
        graph.Attr.LayerDirection = LayerDirection.LR;

        var a = graph.AddNode("1255");
        var b = graph.AddNode("2235");
        var c = graph.AddNode("4141");
        var d = graph.AddNode("4547");

        graph.FindNode("1255").LabelText = "1";
        graph.FindNode("2235").LabelText = "2";
        graph.FindNode("4141").LabelText = "3";
        graph.FindNode("4547").LabelText = "4";

        graph.AddEdge("1255", "2235");
        graph.AddEdge("4141", "4547");

        GeometryGraph geometryGraph = graph.CreateGeometryGraph();
        SetNodeBoundary(a);
        SetNodeBoundary(b);
        SetNodeBoundary(c);
        SetNodeBoundary(d);

        a.GeometryNode.Center = new Point(150, 150);
        b.GeometryNode.Center = new Point(170, 170);
        c.GeometryNode.Center = new Point(150, 180);
        d.GeometryNode.Center = new Point(170, 190);

        var router = new Microsoft.Msagl.Routing.SplineRouter(geometryGraph, new EdgeRoutingSettings());
        router.Run();
        geometryGraph.UpdateBoundingBox();

        gviewer.Graph = graph;
        gviewer.ToolBarIsVisible = false;
        form.SuspendLayout();
        form.Controls.Add(gviewer);
        form.ResumeLayout();
        form.ShowDialog();

    }

`

So for example in this, A and C nodes should be in one box, and B and D in the other, connected as shown in here. Of course all this drawing should be made in the code, because the final result should be "ready for saving as image".

Thank you for your help!

lafrank commented 3 years ago

So below is a skeleton code just to scratch the surface, let's see if it works for you.

... Point mp = MousePosition; var p = gviewer .ScreenToSource(PointToClient(mp)); AnnotationRectangle ar = new AnnotationRectangle(); ar.BaseRectangle = new Rectangle((int)p.X, (int)p.Y, 800, 300); ar.FrameColor = System.Drawing.Color.CornflowerBlue; ar.FillColor = System.Drawing.Color.AliceBlue; var lbl = ar.AddLabel("Show me"); lbl.DisplayFont.Size = 32; ar.OpacityLevel = 100; gviewer.AddAnnotationObject(ar); ...

For further object properties and annotation objects you can look into AnnotationObjects.cs in solution GraphLayout project GraphViewerGDI. And once again, Annotation objects have nothing to do with graph nodes, they live a separate life. Said that, don't try to find any type of relation int between a node and an annotation object, like you can't control which box a node is being drawn in. They are simply annotations.

Regards, Laszlo

On Mon, Jul 12, 2021 at 4:47 PM NiklasVJM @.***> wrote:

Hi!

Thank you for your reply!

Yes, I would be very interested to have a little sample data to act as a guide. Right now, I have something like this:

` private void ConnectionsDialogGraph_Loaded(object sender, RoutedEventArgs e) { var gviewer = new GViewer(); var form = CreateOrAttachForm(gviewer, null); gviewer.NeedToCalculateLayout = false;

    Graph graph = new Graph();
    graph.Attr.LayerDirection = LayerDirection.LR;

    var a = graph.AddNode("1255");
    var b = graph.AddNode("2235");
    var c = graph.AddNode("4141");
    var d = graph.AddNode("4547");

    graph.FindNode("1255").LabelText = "1";
    graph.FindNode("2235").LabelText = "2";
    graph.FindNode("4141").LabelText = "3";
    graph.FindNode("4547").LabelText = "4";

    graph.AddEdge("1255", "2235");
    graph.AddEdge("4141", "4547");

    GeometryGraph geometryGraph = graph.CreateGeometryGraph();
    SetNodeBoundary(a);
    SetNodeBoundary(b);
    SetNodeBoundary(c);
    SetNodeBoundary(d);

    a.GeometryNode.Center = new Point(150, 150);
    b.GeometryNode.Center = new Point(170, 170);
    c.GeometryNode.Center = new Point(150, 180);
    d.GeometryNode.Center = new Point(170, 190);

    var router = new Microsoft.Msagl.Routing.SplineRouter(geometryGraph, new EdgeRoutingSettings());
    router.Run();
    geometryGraph.UpdateBoundingBox();

    gviewer.Graph = graph;
    gviewer.ToolBarIsVisible = false;
    form.SuspendLayout();
    form.Controls.Add(gviewer);
    form.ResumeLayout();
    form.ShowDialog();

}

`

So for example in this, A and C nodes should be in one box, and B and D in the other, connected as shown in here. Of course all this drawing should be made in the code, because the final result should be "ready for saving as image".

Thank you for your help!

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/microsoft/automatic-graph-layout/issues/288#issuecomment-878341155, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADXZOZGD7XHDHC3NZ6U2KM3TXL6AXANCNFSM5AGXZDEQ .

NiklasVJM commented 3 years ago

Thank you so much for this code snippet! I'll have a look, but this looks like it is going to solve my problem.

Thank you so much for your help!