MSAGL:您能否强制从节点上的固定位置绘制边缘线,例如节点的四个基本边界中点?

MSAGL: Can you force edge lines to be drawn from a fixed location on a node like the node's four cardinal border midpoints?

是否可以强制从节点的四个基本边界中点绘制边线?即节点边界上的十二点钟、三点钟、六点钟和九点钟位置,类似于 Visio 或 PowerPoint 中的连接器。

我给 MSAGL 的主要作者 Lev Nachmanson 发了邮件,他很友好地回复了。他确认,截至 2022 年 1 月,MSAGL 目前没有此类功能。

编辑 1: MSAGL 有 FloatingPort 个对象 看起来 就像它们可以用来手动定位边的端点行:Edge 对象具有 SourcePortTargetPort 属性。我还没有找到任何关于如何实际使用这些的文档或教程。任何指点表示赞赏。

编辑 2: 可以通过计算一次布局,然后 post-layout,强制 EdgeRouter 重新路由 foreach 中的所有边来完成循环。

我从 and https://github.com/microsoft/automatic-graph-layout/issues/250 和大量的试验和错误中汲取了大量灵感。

private void Button1_Click(object sender, EventArgs e)
{
    //gViewer1.Invalidate();
    gViewer1.CalculateLayout(_visgraph);
    
    Microsoft.Msagl.Routing.InteractiveEdgeRouter edgeRouter = new Microsoft.Msagl.Routing.InteractiveEdgeRouter(_visgraph.GeometryGraph.Nodes.Select(n => n.BoundaryCurve), 3, 0.65 * 3, 0);
    edgeRouter.Run();

    Microsoft.Msagl.Core.Geometry.SmoothedPolyline ignore;
    foreach (var edge in _visgraph.GeometryGraph.Edges)
    {
        Microsoft.Msagl.Core.Layout.FloatingPort p1 = 
            new Microsoft.Msagl.Core.Layout.FloatingPort(edge.Source.BoundaryCurve
                                                        , new Microsoft.Msagl.Core.Geometry.Point(edge.Source.BoundingBox.Right
                                                                                                 ,edge.Source.BoundingBox.Center.Y));
        Microsoft.Msagl.Core.Layout.FloatingPort p2 = 
            new Microsoft.Msagl.Core.Layout.FloatingPort(edge.Target.BoundaryCurve
                                                        , new Microsoft.Msagl.Core.Geometry.Point(edge.Target.BoundingBox.Left
                                                                                                 ,edge.Target.BoundingBox.Center.Y));

        edge.SourcePort = p1;
        edge.TargetPort = p2;
        edge.Curve = edgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(edge.SourcePort, edge.TargetPort, true, out ignore);

        Microsoft.Msagl.Core.Layout.Arrowheads.TrimSplineAndCalculateArrowheads(edge
                                                                               ,edge.Curve
                                                                               ,true
                                                                               ,true);
    }
}