/// <summary> /// The function FeasibleTree constructs an initial feasible spanning tree. /// </summary> void FeasibleTree() { InitLayer(); while (TightTree() < this.graph.NodeCount) { PolyIntEdge 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 RouteEdgeWithLabel(PolyIntEdge 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); }
internal static int GetSource(ref int currentVV, PolyIntEdge e, int i) { if (i == 0) { return(e.Source); } return(currentVV++); }
internal static int GetTarget(ref int currentVV, PolyIntEdge e, int i, int span) { if (i < span - 1) { return(currentVV); } return(e.Target); }
///// <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, PolyIntEdge 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 PolyIntEdge GluedIntEdge(PolyIntEdge intEdge) { int sourceRepr = NodeToRepr(intEdge.Source); int targetRepr = NodeToRepr(intEdge.Target); PolyIntEdge ie = new PolyIntEdge(sourceRepr, targetRepr); ie.Separation = intEdge.Separation; ie.Weight = 0; ie.Edge = intEdge.Edge; return(ie); }
void RouteEdge(PolyIntEdge edge) { if (edge.HasLabel) { RouteEdgeWithLabel(edge, edge.Edge.Label); } else { RouteEdgeWithNoLabel(edge); } }
/// <summary> /// Creates a smoothed polyline /// </summary> internal SmoothedPolylineCalculator(PolyIntEdge 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; eastHierarchy = BuildEastHierarchy(); westHierarchy = BuildWestHierarchy(); }
int Slack(PolyIntEdge 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); }
void CreateSplineForNonSelfEdge(PolyIntEdge 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); } } }
void DrawSplineBySmothingThePolyline(PolyIntEdge edgePath, bool optimizeShortEdges) { var smoothedPolyline = new SmoothedPolylineCalculator(edgePath, Database.Anchors, OriginalGraph, settings, LayerArrays, ProperLayeredGraph, Database); ICurve spline = smoothedPolyline.GetSpline(optimizeShortEdges); if (edgePath.Reversed) { edgePath.Curve = spline.Reverse(); edgePath.UnderlyingPolyline = smoothedPolyline.Reverse().GetPolyline; } else { edgePath.Curve = spline; edgePath.UnderlyingPolyline = smoothedPolyline.GetPolyline; } }
void RouteEdgeWithNoLabel(PolyIntEdge 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); 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() { PolyIntEdge 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(PolyIntEdge edge) { IntPair ip = new IntPair(edge.Source, edge.Target); List <PolyIntEdge> o; if (multiedges.ContainsKey(ip) == false) { multiedges[ip] = o = new List <PolyIntEdge>(); } 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 <PolyIntEdge> list in database.RegularMultiedges) { int span = 0; PolyIntEdge 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; } } }
/// <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]) { PolyIntEdge e = virtNodesToIntEdges[v]; if (e != null) { int layerOffsetInTheEdge = NLayering[e.Source] - NLayering[v]; List <PolyIntEdge> list = database.Multiedges[new IntPair(e.Source, e.Target)]; foreach (PolyIntEdge 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++; } } } }
public int[] GetLayers() { //sort the vertices in topological order int[] topoOrder = PolyIntEdge.GetOrder(graph); int[] layering = new int[graph.NodeCount]; //going backward from leaves int k = graph.NodeCount; while (k-- > 0) { int v = topoOrder[k]; foreach (PolyIntEdge e in graph.InEdges(v)) { int u = e.Source; int l = layering[v] + e.Separation; if (layering[u] < l) { layering[u] = l; } } } return(layering); }
void CreateLayerEdgesUnderIntEdge(PolyIntEdge 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); } }
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 <PolyIntEdge> edges = new List <PolyIntEdge>(); 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 PolyIntEdge(v, root[rightNeighbor])); } w = align[w]; }while (w != v); } } BasicGraphOnEdges <PolyIntEdge> blockGraph = new BasicGraphOnEdges <PolyIntEdge>(edges, nOfVertices); //sort the graph in the topological order int[] topoSort = PolyIntEdge.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(PolyIntEdge e) { return(e.LayerEdges[e.LayerEdges.Count - 1]); }
private static LayerEdge FirstEdge(PolyIntEdge e) { return(e.LayerEdges[0]); }
internal NetworkEdge(PolyIntEdge e) : base(e.Source, e.Target) { Weight = e.Weight; Separation = e.Separation; }
private bool FanAtSourceOrTarget(PolyIntEdge intEdge) { return ProperLayeredGraph.OutDegreeIsMoreThanOne(intEdge.Source) || ProperLayeredGraph.InDegreeIsMoreThanOne(intEdge.Target); }
internal static NodeKind GetNodeKind(int vertexOffset, PolyIntEdge edgePath) { return vertexOffset == 0 ? NodeKind.Top : (vertexOffset < edgePath.Count ? NodeKind.Internal : NodeKind.Bottom); }
private IntPair GluedIntPair(PolyIntEdge p) { return(new IntPair(NodeToRepr(p.Source), NodeToRepr(p.Target))); }
private bool EdgeIsFlat(PolyIntEdge ie) { return(la.Y[ie.Source] == la.Y[ie.Target]); }