public static void DrawCrossEdges(DGraph graph, IEnumerable <DEdge> edges) { GeometryGraph ggAux = new GeometryGraph(); Dictionary <DNode, GeometryNode> nodeMap = new Dictionary <DNode, GeometryNode>(); foreach (DEdge edge in edges) { if (edge.Label != null) { edge.Label.MeasureLabel(); } nodeMap[edge.Source] = null; nodeMap[edge.Target] = null; } FillAuxGraph(ggAux, graph, new GeometryPoint(0.0, 0.0), nodeMap); Dictionary <DEdge, GeometryEdge> edgeMap = new Dictionary <DEdge, GeometryEdge>(); foreach (DEdge edge in edges) { GeometryEdge gEdge = new GeometryEdge(nodeMap[edge.Source], nodeMap[edge.Target]) { GeometryParent = ggAux }; gEdge.EdgeGeometry.SourceArrowhead = edge.GeometryEdge.EdgeGeometry.SourceArrowhead; gEdge.EdgeGeometry.TargetArrowhead = edge.GeometryEdge.EdgeGeometry.TargetArrowhead; gEdge.Label = edge.GeometryEdge.Label; edgeMap[edge] = gEdge; ggAux.Edges.Add(gEdge); } var router = new SplineRouter(ggAux, 3.0, 2.0, Math.PI / 6.0) { ContinueOnOverlaps = true }; router.Run(); foreach (DEdge edge in edges) { edge.GeometryEdge = edgeMap[edge]; if (edge.DrawingEdge.Label != null) { if (edge.GeometryEdge.Label.Center == new GeometryPoint()) { edge.GeometryEdge.Label.Center = edge.GeometryEdge.BoundingBox.Center; } edge.DrawingEdge.Label.GeometryLabel = edge.GeometryEdge.Label; } } foreach (DEdge edge in edges) { edge.MakeVisual(); Canvas.SetZIndex(edge, 20000); graph.MainCanvas.Children.Add(edge); if (edge.Label != null) { edge.Label.MakeVisual(); Canvas.SetZIndex(edge.Label, 20000); graph.MainCanvas.Children.Add(edge.Label); } } }
public static Graph CreateDrawingGraph(GeometryGraph gg) { counter = 0; localMap = new Dictionary <GeometryNode, Node>(); dg = new Graph(counter++.ToString()) { GeometryGraph = gg }; foreach (GeometryNode n in gg.Nodes) { Node node = new Node(counter++.ToString()); node.Attr.Shape = Shape.Ellipse; node.GeometryNode = n; dg.AddNode(node); localMap[n] = node; } Subgraph cluster = new Subgraph(counter++.ToString()); cluster.GeometryNode = gg.RootCluster; dg.RootSubgraph = cluster; PopulateClusters(cluster, gg.RootCluster); foreach (GeometryEdge e in gg.Edges) { Edge edge = new Edge(localMap[e.Source], localMap[e.Target], ConnectionToGraph.Disconnected); edge.Attr.ArrowheadAtSource = e.ArrowheadAtSource ? ArrowStyle.Normal : ArrowStyle.None; edge.Attr.ArrowheadAtTarget = e.ArrowheadAtTarget ? ArrowStyle.Normal : ArrowStyle.None; edge.GeometryEdge = e; dg.AddPrecalculatedEdge(edge); } //PopulateClusterEdges(dg.RootSubgraph, gg.RootCluster); return(dg); }
public static Graph CreateDrawingGraph(GeometryGraph gg) { counter = 0; localMap = new Dictionary<GeometryNode,Node>(); dg = new Graph(counter++.ToString()) { GeometryGraph = gg }; foreach (GeometryNode n in gg.Nodes) { Node node = new Node(counter++.ToString()); node.Attr.Shape = Shape.Ellipse; node.GeometryNode = n; dg.AddNode(node); localMap[n]=node; } Subgraph cluster = new Subgraph(counter++.ToString()); cluster.GeometryNode = gg.RootCluster; dg.RootSubgraph = cluster; PopulateClusters(cluster, gg.RootCluster); foreach (GeometryEdge e in gg.Edges) { Edge edge = new Edge(localMap[e.Source], localMap[e.Target], ConnectionToGraph.Disconnected); edge.Attr.ArrowheadAtSource = e.ArrowheadAtSource ? ArrowStyle.Normal : ArrowStyle.None; edge.Attr.ArrowheadAtTarget = e.ArrowheadAtTarget ? ArrowStyle.Normal : ArrowStyle.None; edge.GeometryEdge = e; dg.AddPrecalculatedEdge(edge); } //PopulateClusterEdges(dg.RootSubgraph, gg.RootCluster); return dg; }
public void SetGeometryGraph(Microsoft.Msagl.Core.Layout.GeometryGraph gg) { GeometryTest.Layout(gg); var dg = FromGeometry.CreateDrawingGraph(gg); var dgraph = DGraph.FromDrawingGraph(dg); dgraph.Name = "From Geometry"; FromGeometryContainer.Children.Insert(0, dgraph); }
private void LayoutLinkedShapes(Graph graph, out Microsoft.Msagl.Core.Layout.GeometryGraph geometry) { var geomGraph = new Microsoft.Msagl.Core.Layout.GeometryGraph(); var layoutSettings = new Microsoft.Msagl.Layout.Layered.SugiyamaLayoutSettings(); Microsoft.Msagl.Core.Layout.Node EnsureNode(Node node) { var res = geomGraph.Nodes.FirstOrDefault(n => n.UserData == node); if (res == null) { var geomNode = new Microsoft.Msagl.Core.Layout.Node( Microsoft.Msagl.Core.Geometry.Curves.CurveFactory.CreateRectangle( ShapeSize, ShapeSize, new Microsoft.Msagl.Core.Geometry.Point() ), node ); geomGraph.Nodes.Add(geomNode); return(geomNode); } return(res); } foreach (var l in graph.Links) { var n1 = EnsureNode(l.Node1); var n2 = EnsureNode(l.Node2); var e = new Microsoft.Msagl.Core.Layout.Edge(n1, n2); geomGraph.Edges.Add(e); } LayoutHelpers.CalculateLayout(geomGraph, layoutSettings, null); foreach (var kv in nodesAndShapes) { var pos = geomGraph.Nodes.FirstOrDefault(n => n.UserData == kv.Key)?.Center; if (pos.HasValue) { kv.Value.X = (int)pos.Value.X + ShapeSize; kv.Value.Y = Diagram.Height - (int)pos.Value.Y + ShapeSize / 2; } } geometry = geomGraph; }
private void CreateDynamicConnectorEdges(Dom.ShapeList shape_nodes, MSAGL.Core.Layout.GeometryGraph mg_graph) { // CREATE EDGES foreach (var edge in mg_graph.Edges) { var ud = (NodeUserData)edge.UserData; var layout_connector = ud.Connector; Dom.Connector vconnector; if (layout_connector.MasterName != null && layout_connector.StencilName != null) { vconnector = new Dom.Connector( layout_connector.From.DOMNode, layout_connector.To.DOMNode, layout_connector.MasterName, layout_connector.StencilName); } else { vconnector = new Dom.Connector( layout_connector.From.DOMNode, layout_connector.To.DOMNode, "Dynamic Connector", "connec_u.vss"); } layout_connector.DOMNode = vconnector; shape_nodes.Add(vconnector); } foreach (var edge in mg_graph.Edges) { var ud = (NodeUserData)edge.UserData; var layoutconnector = ud.Connector; var vconnector = (Dom.Connector)layoutconnector.DOMNode; int con_route_style = (int)this.ConnectorTypeToCellVal_Appearance(layoutconnector.ConnectorType); int shape_route_style = (int)this.ConnectorTypeToCellVal_Style(layoutconnector.ConnectorType); vconnector.Text = new VisioAutomation.Models.Text.TextElement(layoutconnector.Label); vconnector.Cells = layoutconnector.Cells != null? layoutconnector.Cells.ShallowCopy() : new Dom.ShapeCells(); vconnector.Cells.ConLineRouteExt = con_route_style; vconnector.Cells.ShapeRouteStyle = shape_route_style; } }
private void CreateBezierEdges(Dom.ShapeList domshapes, MSAGL.Core.Layout.GeometryGraph mg_graph) { // DRAW EDGES WITH BEZIERS foreach (var mg_edge in mg_graph.Edges) { var ud = (NodeUserData)mg_edge.UserData; var layoutconnector = ud.Connector; var vconnector = this.draw_edge_bezier(mg_edge); layoutconnector.DOMNode = vconnector; domshapes.Add(vconnector); } foreach (var mg_edge in mg_graph.Edges) { var ud = (NodeUserData)mg_edge.UserData; var layout_connector = ud.Connector; if (layout_connector.Cells != null) { var bezier_node = (Dom.BezierCurve)layout_connector.DOMNode; bezier_node.Cells = layout_connector.Cells.ShallowCopy(); } } foreach (var mg_edge in mg_graph.Edges) { var ud = (NodeUserData)mg_edge.UserData; var layout_connector = ud.Connector; if (!string.IsNullOrEmpty(layout_connector.Label)) { // this is a bezier connector // draw a manual box instead var label_bb = this.ToDocumentCoordinates(MsaglUtil.ToVARectangle(mg_edge.Label.BoundingBox)); var vshape = new Dom.Rectangle(label_bb); domshapes.Add(vshape); vshape.Cells = this.DefaultBezierConnectorShapeCells.ShallowCopy(); vshape.Text = new VisioAutomation.Models.Text.TextElement(layout_connector.Label); } } }
private void LayoutFreeShapes(Microsoft.Msagl.Core.Layout.GeometryGraph geometry) { var xs = geometry.Nodes.Select(n => n.Center.X); var right = xs.Any() ? xs.Max() + ShapeSize * 3 : ShapeSize; var freeShapes = nodesAndShapes.Where(kv => geometry.Nodes.All(n => n.UserData != kv.Key)).Select(kv => kv.Value).ToArray(); var priorities = freeShapes.Select(s => { var q = nodesAndShapes[s].Quest; if (!q.IsLinksToEditable()) { return(3); } if (!q.IsActive()) { return(2); } return(1); }).ToArray(); Array.Sort(priorities, freeShapes); var width = Diagram.Size.Width - right; var columnsCount = Math.Max(1, width / ShapeSize - 1); int curColumn = 0; int curRow = 0; foreach (var s in freeShapes) { s.X = curColumn * ShapeSize + (int)right; s.Y = curRow * ShapeSize + ShapeSize / 2; ++curColumn; if (curColumn >= columnsCount) { curColumn = 0; ++curRow; } } }
/// <summary> /// Creates an auxilliary geometry graph, which contains all the nodes of a flattened nested graph. Produces a map from the original graph nodes to the auxilliary graph nodes. /// </summary> /// <param name="gg">The auxilliary graph to be filled.</param> /// <param name="graph">The original graph.</param> /// <param name="offset">Offset to be applied to all nodes.</param> /// <param name="connectedNodes">Map from original graph nodes to auxilliary graph nodes.</param> private static void FillAuxGraph(GeometryGraph gg, DGraph graph, GeometryPoint offset, Dictionary <DNode, GeometryNode> connectedNodes) { foreach (DNode n in graph.Nodes()) { GeometryNode clone = new GeometryNode(n.GeometryNode.BoundaryCurve.Clone()); clone.BoundaryCurve.Translate(offset); gg.Nodes.Add(clone); connectedNodes[n] = clone; DNestedGraphLabel ngLabel = n.Label as DNestedGraphLabel; if (ngLabel != null) { GeometryPoint labelPosition = new GeometryPoint(Canvas.GetLeft(ngLabel), Canvas.GetTop(ngLabel)); foreach (DGraph dg in ngLabel.Graphs) { Point p = ngLabel.GetDGraphOffset(dg); GeometryPoint offsetToLabel = new GeometryPoint(p.X, p.Y); GeometryPoint graphOffset = labelPosition + offsetToLabel; GeometryPoint normalizedOffset = graphOffset - dg.Graph.BoundingBox.LeftBottom; FillAuxGraph(gg, dg, offset + normalizedOffset, connectedNodes); } } } }
private MSAGL.Core.Layout.GeometryGraph CreateMsaglGraph(DirectedGraphLayout layout_diagram) { var mg_graph = new MSAGL.Core.Layout.GeometryGraph(); // Create the nodes in MSAGL foreach (var layout_shape in layout_diagram.Shapes) { var nodesize = this.ToMGCoordinates(layout_shape.Size ?? this.LayoutOptions.DefaultShapeSize); var node_user_data = new NodeUserData(layout_shape.ID, layout_shape); var center = new MSAGL.Core.Geometry.Point(); var rectangle = MSAGL.Core.Geometry.Curves.CurveFactory.CreateRectangle(nodesize.Width, nodesize.Height, center); var mg_node = new MSAGL.Core.Layout.Node(rectangle, node_user_data); mg_graph.Nodes.Add(mg_node); } this.validate_connectors(layout_diagram); var mg_coordinates = this.ToMGCoordinates(this.DefaultBezierConnectorLabelBoxSize); var map_id_to_ud = new Dictionary <string, MSAGL.Core.Layout.Node>(); foreach (var n in mg_graph.Nodes) { var ud = (NodeUserData)n.UserData; if (ud != null) { map_id_to_ud[ud.ID] = n; } } // Create the MG Connectors foreach (var layout_connector in layout_diagram.Connectors) { if (layout_connector.From == null) { throw new ArgumentException("Connector's From node is null"); } if (layout_connector.To == null) { throw new ArgumentException("Connector's To node is null"); } var from_node = map_id_to_ud[layout_connector.From.ID]; var to_node = map_id_to_ud[layout_connector.To.ID]; var new_edge = new MSAGL.Core.Layout.Edge(from_node, to_node); // TODO: MSAGL //new_edge.ArrowheadAtTarget = false; new_edge.UserData = new NodeUserData(layout_connector.ID, layout_connector); mg_graph.Edges.Add(new_edge); new_edge.Label = new MSAGL.Core.Layout.Label(mg_coordinates.Width, mg_coordinates.Height, new_edge); } var geom_graph_components = MSAGL.Core.Layout.GraphConnectedComponents.CreateComponents(mg_graph.Nodes, mg_graph.Edges); var settings = new MSAGL.Layout.Layered.SugiyamaLayoutSettings(); foreach (var subgraph in geom_graph_components) { var layout = new Microsoft.Msagl.Layout.Layered.LayeredLayout(subgraph, settings); subgraph.Margins = settings.NodeSeparation / 2; layout.Run(); } // Pack the graphs using Golden Aspect Ratio MSAGL.Layout.MDS.MdsGraphLayout.PackGraphs(geom_graph_components, settings); //Update the graphs bounding box mg_graph.UpdateBoundingBox(); this._mg_bb = new VA.Drawing.Rectangle( mg_graph.BoundingBox.Left, mg_graph.BoundingBox.Bottom, mg_graph.BoundingBox.Right, mg_graph.BoundingBox.Top); this._layout_bb = new VA.Drawing.Rectangle(0, 0, this._mg_bb.Width, this._mg_bb.Height) .Multiply(this.ScaleToDocument, this.ScaleToDocument); return(mg_graph); }
private void CreateDOMShapes(Dom.ShapeList domshapeslist, MSAGL.Core.Layout.GeometryGraph mg_graph, IVisio.Application app) { var node_centerpoints = mg_graph.Nodes .Select(n => this.ToDocumentCoordinates(MsaglUtil.ToVAPoint(n.Center))) .ToArray(); // Load up all the stencil docs var app_documents = app.Documents; var uds = mg_graph.Nodes.Where(n => n.UserData != null).Select(n => (NodeUserData)n.UserData).ToList(); var shapes = uds.Where(ud => ud.Shape != null).Select(ud => ud.Shape).ToList(); var stencilnames0 = shapes.Select(s => s.StencilName).ToList(); var stencil_names = stencilnames0.Distinct().ToList(); var compare = StringComparer.InvariantCultureIgnoreCase; var stencil_map = new Dictionary <string, IVisio.Document>(compare); foreach (var stencil_name in stencil_names) { if (!stencil_map.ContainsKey(stencil_name)) { var stencil = app_documents.OpenStencil(stencil_name); stencil_map[stencil_name] = stencil; } } var master_map = new Dictionary <string, IVisio.Master>(compare); foreach (var nv in shapes) { var key = nv.StencilName + "+" + nv.MasterName; if (!master_map.ContainsKey(key)) { var stencil = stencil_map[nv.StencilName]; var masters = stencil.Masters; var master = masters[nv.MasterName]; master_map[key] = master; } } // Create DOM Shapes for each AutoLayoutShape int count = 0; foreach (var layout_shape in shapes) { var key = layout_shape.StencilName.ToLower() + "+" + layout_shape.MasterName; var master = master_map[key]; var shape_node = new Dom.Shape(master, node_centerpoints[count]); layout_shape.DOMNode = shape_node; domshapeslist.Add(shape_node); count++; } // FORMAT EACH SHAPE foreach (var n in mg_graph.Nodes) { var ud = (NodeUserData)n.UserData; var layout_shape = ud.Shape; if (layout_shape != null) { this.format_shape(layout_shape, layout_shape.DOMNode); } } }
private MSAGL.Core.Layout.GeometryGraph _create_msagl_graph(DirectedGraphLayout dglayout) { var msagl_graph = new MSAGL.Core.Layout.GeometryGraph(); // Create the nodes in MSAGL foreach (var layout_shape in dglayout.Nodes) { var nodesize = this._to_mg_coordinates(layout_shape.Size ?? this.LayoutOptions.DefaultShapeSize); var node_user_data = new ElementUserData(layout_shape.ID, layout_shape); var center = new MSAGL.Core.Geometry.Point(); var rectangle = MSAGL.Core.Geometry.Curves.CurveFactory.CreateRectangle(nodesize.Width, nodesize.Height, center); var mg_node = new MSAGL.Core.Layout.Node(rectangle, node_user_data); msagl_graph.Nodes.Add(mg_node); } this.validate_connectors(dglayout); var mg_coordinates = this._to_mg_coordinates(this.DefaultBezierConnectorLabelBoxSize); var map_id_to_ud = new Dictionary <string, MSAGL.Core.Layout.Node>(); foreach (var n in msagl_graph.Nodes) { var ud = (ElementUserData)n.UserData; if (ud != null) { map_id_to_ud[ud.ID] = n; } } // Create the MG Connectors foreach (var layout_connector in dglayout.Edges) { if (layout_connector.From == null) { throw new ArgumentException("Connector's From node is null"); } if (layout_connector.To == null) { throw new ArgumentException("Connector's To node is null"); } var from_node = map_id_to_ud[layout_connector.From.ID]; var to_node = map_id_to_ud[layout_connector.To.ID]; var new_edge = new MSAGL.Core.Layout.Edge(from_node, to_node); // TODO: MSAGL //new_edge.ArrowheadAtTarget = false; new_edge.UserData = new ElementUserData(layout_connector.ID, layout_connector); msagl_graph.Edges.Add(new_edge); new_edge.Label = new MSAGL.Core.Layout.Label(mg_coordinates.Width, mg_coordinates.Height, new_edge); } var msagl_graphs = MSAGL.Core.Layout.GraphConnectedComponents.CreateComponents(msagl_graph.Nodes, msagl_graph.Edges); var msagl_sugiyamasettings = new MSAGL.Layout.Layered.SugiyamaLayoutSettings(); if (this.LayoutOptions.Direction == MsaglDirection.TopToBottom) { // do nothing } else if (this.LayoutOptions.Direction == MsaglDirection.BottomToTop) { msagl_sugiyamasettings.Transformation = MSAGL.Core.Geometry.Curves.PlaneTransformation.Rotation(Math.PI); } else if (this.LayoutOptions.Direction == MsaglDirection.LeftToRight) { msagl_sugiyamasettings.Transformation = MSAGL.Core.Geometry.Curves.PlaneTransformation.Rotation(Math.PI / 2); } else if (this.LayoutOptions.Direction == MsaglDirection.RightToLeft) { msagl_sugiyamasettings.Transformation = MSAGL.Core.Geometry.Curves.PlaneTransformation.Rotation(-Math.PI / 2); } else { throw new System.ArgumentOutOfRangeException(); } foreach (var subgraph in msagl_graphs) { var layout = new Microsoft.Msagl.Layout.Layered.LayeredLayout(subgraph, msagl_sugiyamasettings); subgraph.Margins = msagl_sugiyamasettings.NodeSeparation / 2; layout.Run(); } // Pack the graphs using Golden Aspect Ratio MSAGL.Layout.MDS.MdsGraphLayout.PackGraphs(msagl_graphs, msagl_sugiyamasettings); //Update the graphs bounding box msagl_graph.UpdateBoundingBox(); this._msagl_bb = new VA.Geometry.Rectangle( msagl_graph.BoundingBox.Left, msagl_graph.BoundingBox.Bottom, msagl_graph.BoundingBox.Right, msagl_graph.BoundingBox.Top); this._visio_bb = new VA.Geometry.Rectangle(0, 0, this._msagl_bb.Width, this._msagl_bb.Height) .Multiply(this._scale_to_document, this._scale_to_document); return(msagl_graph); }