/// <summary> /// Original layers are represented by even layers in the new layering. /// Here we add new virtices in such layers and /// set new x-offsets of original and dummy vertices in these layers. /// </summary> void WidenOriginalLayers() { for (int i = 0; i < la.Layers.Length; i++) { int[] layer = nla.Layers[i * 2]; int offset = 0; foreach (int v in la.Layers[i]) { IntEdge e = virtNodesToIntEdges[v]; if (e != null) { int layerOffsetInTheEdge = NLayering[e.Source] - NLayering[v]; List<IntEdge> list = database.Multiedges[new IntPair(e.Source, e.Target)]; foreach (IntEdge ie in list) { if (ie != e) { int u = ie.LayerEdges[layerOffsetInTheEdge].Source; layer[offset] = u; nla.X[u] = offset++; } else { layer[offset] = v; nla.X[v] = offset++; } } } else { layer[offset] = v; nla.X[v] = offset++; } } } }
void RouteEdgeWithLabel(IntEdge intEdge, Label label) { //we allow here for the edge to cross its own label Node sourceNode = routing.IntGraph.Nodes[intEdge.Source]; Node targetNode = routing.IntGraph.Nodes[intEdge.Target]; var sourcePort = new FloatingPort(sourceNode.BoundaryCurve, sourceNode.Center); var targetPort = new FloatingPort(targetNode.BoundaryCurve, targetNode.Center); ICurve labelObstacle = labelsToLabelObstacles[label]; var labelPort = new FloatingPort(labelObstacle, label.Center); SmoothedPolyline poly0; interactiveEdgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(sourcePort, labelPort, true, out poly0); SmoothedPolyline poly1; interactiveEdgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(labelPort, targetPort, true, out poly1); Site site = poly1.HeadSite.Next; Site lastSite = poly0.LastSite; lastSite.Next = site; site.Previous = lastSite; var eg = intEdge.Edge.EdgeGeometry; eg.SetSmoothedPolylineAndCurve(poly0); Arrowheads.TrimSplineAndCalculateArrowheads(eg, intEdge.Edge.Source.BoundaryCurve, intEdge.Edge.Target.BoundaryCurve, eg.Curve, false, settings.EdgeRoutingSettings.KeepOriginalSpline); }
/// <summary> /// The function FeasibleTree constructs an initial feasible spanning tree. /// </summary> void FeasibleTree() { InitLayer(); while (TightTree() < this.graph.NodeCount) { IntEdge e = GetNonTreeEdgeIncidentToTheTreeWithMinimalAmountOfSlack(); if (e == null) { break; //all edges are tree edges } int slack = Slack(e); if (slack == 0) { throw new InvalidOperationException();//"the tree should be tight"); } if (inTree[e.Source]) { slack = -slack; } //shift the tree rigidly up or down and make e tight ; since the slack is the minimum of slacks //the layering will still remain feasible foreach (int i in treeVertices) { layers[i] += slack; } } InitCutValues(); }
void CreateLayerEdgesUnderIntEdge(IntEdge ie) { int source = ie.Source; int target = ie.Target; int span = LayeredLayoutEngine.EdgeSpan(initialLayering, ie); ie.LayerEdges = new LayerEdge[span]; Debug.Assert(span > 0); if (span == 1) { ie.LayerEdges[0] = new LayerEdge(ie.Source, ie.Target, ie.CrossingWeight); } else { ie.LayerEdges[0] = new LayerEdge(source, numberOfNodesOfProperGraph, ie.CrossingWeight); for (int i = 0; i < span - 2; i++) { ie.LayerEdges[i + 1] = new LayerEdge(numberOfNodesOfProperGraph++, numberOfNodesOfProperGraph, ie.CrossingWeight); } ie.LayerEdges[span - 1] = new LayerEdge(numberOfNodesOfProperGraph++, target, ie.CrossingWeight); } }
///// <summary> ///// mark the vertex as one representing a label ///// or a middle of a multi edge ///// </summary> ///// <param name="db"></param> ///// <param name="bucket"></param> ///// <param name="parent"></param> ///// <param name="i"></param> internal static void RegisterDontStepOnVertex(Database db, IntEdge parent) { if (db.Multiedges[new IntPair(parent.Source, parent.Target)].Count > 1) { LayerEdge e = parent.LayerEdges[parent.LayerEdges.Count / 2]; db.MultipleMiddles.Insert(e.Source); } }
internal static int GetSource(ref int currentVV, IntEdge e, int i) { if (i == 0) { return(e.Source); } return(currentVV++); }
internal static int GetTarget(ref int currentVV, IntEdge e, int i, int span) { if (i < span - 1) { return(currentVV); } return(e.Target); }
internal IntEdge GluedIntEdge(IntEdge intEdge) { int sourceRepr = NodeToRepr(intEdge.Source); int targetRepr = NodeToRepr(intEdge.Target); IntEdge ie = new IntEdge(sourceRepr, targetRepr); ie.Separation = intEdge.Separation; ie.Weight = 0; ie.Edge = intEdge.Edge; return(ie); }
void RouteEdge(IntEdge edge) { if (edge.HasLabel) { RouteEdgeWithLabel(edge, edge.Edge.Label); } else { RouteEdgeWithNoLabel(edge); } }
int Slack(IntEdge e) { int ret = layers[e.Source] - layers[e.Target] - e.Separation; #if DEBUGNW if (ret < 0) { throw new Exception("separation is not satisfied"); } #endif return(ret); }
/// <summary> /// Creates a smoothed polyline /// </summary> internal SmoothedPolylineCalculator(IntEdge edgePathPar, Anchor[] anchorsP, GeometryGraph origGraph, SugiyamaLayoutSettings settings, LayerArrays la, ProperLayeredGraph layerGraph, Database databaseP) { this.database = databaseP; edgePath = edgePathPar; anchors = anchorsP; this.layerArrays = la; this.originalGraph = origGraph; this.settings = settings; this.layeredGraph = layerGraph; rightHierarchy = BuildRightHierarchy(); leftHierarchy = BuildLeftHierarchy(); }
void DrawSplineBySmothingThePolyline(IntEdge edgePath) { var smoothedPolyline = new SmoothedPolylineCalculator(edgePath, Database.Anchors, OriginalGraph, settings, LayerArrays, ProperLayeredGraph, Database); ICurve spline = smoothedPolyline.GetSpline(); if (edgePath.Reversed) { edgePath.Curve = spline.Reverse(); edgePath.UnderlyingPolyline = smoothedPolyline.Reverse().GetPolyline; } else { edgePath.Curve = spline; edgePath.UnderlyingPolyline = smoothedPolyline.GetPolyline; } }
void CreateSplineForNonSelfEdge(IntEdge es, bool optimizeShortEdges) { this.ProgressStep(); if (es.LayerEdges != null) { DrawSplineBySmothingThePolyline(es, optimizeShortEdges); if (!es.IsVirtualEdge) { es.UpdateEdgeLabelPosition(Database.Anchors); Arrowheads.TrimSplineAndCalculateArrowheads(es.Edge.EdgeGeometry, es.Edge.Source.BoundaryCurve, es.Edge.Target.BoundaryCurve, es.Curve, true, settings.EdgeRoutingSettings.KeepOriginalSpline); } } }
void RouteEdgeWithNoLabel(IntEdge intEdge) { Node sourceNode = routing.IntGraph.Nodes[intEdge.Source]; Node targetNode = routing.IntGraph.Nodes[intEdge.Target]; var sourcePort = new FloatingPort(sourceNode.BoundaryCurve, sourceNode.Center); var targetPort = new FloatingPort(targetNode.BoundaryCurve, targetNode.Center); var eg = intEdge.Edge.EdgeGeometry; SmoothedPolyline sp; eg.Curve = interactiveEdgeRouter.RouteSplineFromPortToPortWhenTheWholeGraphIsReady(sourcePort, targetPort, true, out sp); Arrowheads.TrimSplineAndCalculateArrowheads(eg, intEdge.Edge.Source.BoundaryCurve, intEdge.Edge.Target.BoundaryCurve, eg.Curve, false, settings.EdgeRoutingSettings.KeepOriginalSpline); intEdge.Edge.EdgeGeometry = eg; }
/// <summary> /// one of the returned edge vertices does not belong to the tree but another does /// </summary> /// <returns></returns> NetworkEdge GetNonTreeEdgeIncidentToTheTreeWithMinimalAmountOfSlack() { IntEdge eret = null; int minSlack = NetworkEdge.Infinity; foreach (int v in this.treeVertices) { foreach (NetworkEdge e in this.graph.OutEdges(v)) { if (inTree[e.Source] && inTree[e.Target]) { continue; } int slack = Slack(e); if (slack < minSlack) { eret = e; minSlack = slack; if (slack == 1) { return(e); } } } foreach (NetworkEdge e in this.graph.InEdges(v)) { if (inTree[e.Source] && inTree[e.Target]) { continue; } int slack = Slack(e); if (slack < minSlack) { eret = e; minSlack = slack; if (slack == 1) { return(e); } } } } return(eret as NetworkEdge); }
internal void RegisterOriginalEdgeInMultiedges(IntEdge edge) { IntPair ip = new IntPair(edge.Source, edge.Target); List <IntEdge> o; if (multiedges.ContainsKey(ip) == false) { multiedges[ip] = o = new List <IntEdge>(); } else { o = multiedges[ip]; } o.Add(edge); }
/// <summary> /// virtual nodes inside of an edge should be of the form i,i+1, .... /// </summary> private void EditOldLayering() { int curVNode = this.intGraph.NodeCount; foreach (List<IntEdge> list in database.RegularMultiedges) { int span = 0; IntEdge e = list[0]; span = e.LayerSpan * 2; if (span > 0) {//ignoring flat edges foreach (LayerEdge le in e.LayerEdges) { if (le.Target != e.Target) { curVNode++; UpdateOldLayer(curVNode++, le.Target); } } curVNode += (span - 1) * (list.Count - 1) + 1; } } }
public int[] GetLayers() { //sort the vertices in topological order int[] topoOrder = IntEdge.GetOrder(graph); int[] layering = new int[graph.NodeCount]; //going backward from leaves int k = graph.NodeCount; while (k-- > 0) { int v = topoOrder[k]; foreach (IntEdge e in graph.InEdges(v)) { int u = e.Source; int l = layering[v] + e.Separation; if (layering[u] < l) { layering[u] = l; } } } return(layering); }
private bool FanAtSourceOrTarget(IntEdge intEdge) { return ProperLayeredGraph.OutDegreeIsMoreThanOne(intEdge.Source) || ProperLayeredGraph.InDegreeIsMoreThanOne(intEdge.Target); }
internal static NodeKind GetNodeKind(int vertexOffset, IntEdge edgePath) { return vertexOffset == 0 ? NodeKind.Top : (vertexOffset < edgePath.Count ? NodeKind.Internal : NodeKind.Bottom); }
private IntPair GluedIntPair(IntEdge p) { return(new IntPair(NodeToRepr(p.Source), NodeToRepr(p.Target))); }
void AssignCoordinatesByLongestPath() { this.x = this.xCoords[this.EnumRightUp] = new double[this.nOfVertices]; /* * We create a graph of blocks or rather of block roots. There is an edge * from u-block to v-block if some of elements of u-block is to the left of v * on the same layer. Then we topologically sort the graph and assign coordinates * taking into account separation between the blocks. */ //create the graph first List <IntEdge> edges = new List <IntEdge>(); for (int v = 0; v < nOfVertices; v++) { if (v == root[v]) //v is a root { int w = v; //w will be running over the block do { int rightNeighbor; if (TryToGetRightNeighbor(w, out rightNeighbor)) { edges.Add(new IntEdge(v, root[rightNeighbor])); } w = align[w]; }while (w != v); } } BasicGraph <IntEdge> blockGraph = new BasicGraph <IntEdge>(edges, nOfVertices); //sort the graph in the topological order int[] topoSort = IntEdge.GetOrder(blockGraph); //start placing the blocks according to the order foreach (int v in topoSort) { if (v == root[v])//not every element of topoSort is a root! { double vx = 0; bool vIsLeftMost = true; int w = v;//w is running over the block do { int wLeftNeighbor; if (TryToGetLeftNeighbor(w, out wLeftNeighbor)) { if (vIsLeftMost) { vx = x[root[wLeftNeighbor]] + DeltaBetweenVertices(wLeftNeighbor, w); vIsLeftMost = false; } else { vx = RightMost(vx, x[root[wLeftNeighbor]] + DeltaBetweenVertices(wLeftNeighbor, w)); } } w = align[w]; }while (w != v); x[v] = vx; } } //push the roots of the graph maximally to the right foreach (int v in topoSort) { if (v == root[v]) { if (blockGraph.InEdges(v).Count == 0) { int w = v;//w runs over the block double xLeftMost = RightMost(-infinity, infinity); double xl = xLeftMost; do { int wRightNeigbor; if (TryToGetRightNeighbor(w, out wRightNeigbor)) { xLeftMost = LeftMost(xLeftMost, x[root[wRightNeigbor]] - DeltaBetweenVertices(w, wRightNeigbor)); } w = align[w]; } while (w != v); //leave the value zero if there are no right neighbours if (xl != xLeftMost) { x[v] = xLeftMost; } } } } for (int v = 0; v < this.nOfVertices; v++) { if (v != root[v]) { x[v] = x[root[v]]; } } }
private static LayerEdge LastEdge(IntEdge e) { return(e.LayerEdges[e.LayerEdges.Count - 1]); }
private static LayerEdge FirstEdge(IntEdge e) { return(e.LayerEdges[0]); }
private bool EdgeIsFlat(IntEdge ie) { return(la.Y[ie.Source] == la.Y[ie.Target]); }
internal NetworkEdge(IntEdge e) : base(e.Source, e.Target) { Weight = e.Weight; Separation = e.Separation; }