/// <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(); }
internal static void Refine( int topNodeP, int bottomNode, Site topSiteP, Anchor[] anchors, LayerArrays layerArraysP, ProperLayeredGraph layeredGraph, GeometryGraph originalGraph, double layerSeparation) { RefinerBetweenTwoLayers refiner = new RefinerBetweenTwoLayers(topNodeP, bottomNode, topSiteP, layerArraysP, layeredGraph, originalGraph, anchors, layerSeparation); refiner.Refine(); }
RefinerBetweenTwoLayers( int topNodeP, int bottomNodeP, Site topSiteP, LayerArrays layerArraysP, ProperLayeredGraph layeredGraphP, GeometryGraph originalGraphP, Anchor[] anchorsP, double layerSeparation) { this.topNode = topNodeP; this.bottomNode = bottomNodeP; this.topSite = topSiteP; this.bottomSite = topSiteP.Next; this.currentTopSite = topSiteP; this.currentBottomSite = topSiteP.Next; this.layerArrays = layerArraysP; this.layeredGraph = layeredGraphP; this.originalGraph = originalGraphP; this.anchors = anchorsP; this.layerSeparation = layerSeparation; }
void GetSuccessorAndPredecessor(int i, out Anchor p, out Anchor s) { int predecessor = 10; //the value does not matter, just to silence the compiler foreach (LayerEdge ie in properLayeredGraph.InEdges(i)) predecessor = ie.Source; // there will be only one int successor = 10; // the value does not matter, just to silence the compiler foreach (LayerEdge ie in properLayeredGraph.OutEdges(i)) successor = ie.Target; //there will be only one //we compare the sum of length of projections of edges (predecessor,i), (i,successor) to x in cases when the label is to the right and to the left p = anchors[predecessor]; s = anchors[successor]; }
static void PutLabelToTheLeft(Anchor a) { double r = a.Right; double t = a.LeftAnchor; a.LeftAnchor = a.RightAnchor; a.RightAnchor = t; a.X = r - a.RightAnchor; a.LabelToTheLeftOfAnchorCenter = true; a.LabelToTheRightOfAnchorCenter = false; }
static bool TryToPutLabelOutsideOfAngle(Anchor a, Anchor predecessor, Anchor successor) { if (a.LabelToTheRightOfAnchorCenter) { if (Point.GetTriangleOrientation(predecessor.Origin, a.Origin, successor.Origin) == TriangleOrientation.Clockwise) return true; double la = a.LeftAnchor; double ra = a.RightAnchor; double x = a.X; PutLabelToTheLeft(a); if (Point.GetTriangleOrientation(predecessor.Origin, a.Origin, successor.Origin) == TriangleOrientation.Counterclockwise) return true; a.X = x; a.LeftAnchor = la; a.RightAnchor = ra; a.LabelToTheRightOfAnchorCenter = true; a.LabelToTheLeftOfAnchorCenter = false; return false; } return false; }
static void CalcAnchorsForOriginalNode(int i, BasicGraph<Node, IntEdge> intGraph, Anchor[] anchors, Database database, SugiyamaLayoutSettings settings) { double leftAnchor = 0; double rightAnchor = leftAnchor; double topAnchor = 0; double bottomAnchor = topAnchor; //that's what we would have without the label and multiedges if (intGraph.Nodes != null) { Node node = intGraph.Nodes[i]; ExtendStandardAnchors(ref leftAnchor, ref rightAnchor, ref topAnchor, ref bottomAnchor, node, settings); } RightAnchorMultiSelfEdges(i, ref rightAnchor, ref topAnchor, ref bottomAnchor, database, settings); double hw = settings.MinNodeWidth/2; if (leftAnchor < hw) leftAnchor = hw; if (rightAnchor < hw) rightAnchor = hw; double hh = settings.MinNodeHeight/2; if (topAnchor < hh) topAnchor = hh; if (bottomAnchor < hh) bottomAnchor = hh; anchors[i] = new Anchor(leftAnchor, rightAnchor, topAnchor, bottomAnchor, intGraph.Nodes[i], settings.LabelCornersPreserveCoefficient) {Padding = intGraph.Nodes[i].Padding}; #if TEST_MSAGL anchors[i].UserData = intGraph.Nodes[i].UserData; #endif }
static void MakeVirtualNodesTall(int[] yLayer, double bottomAnchorMax, double topAnchorMax, int originalNodeCount, Anchor[] anchors) { if (LayerIsOriginal(yLayer, originalNodeCount)) foreach (int j in yLayer) if (j >= originalNodeCount) { Anchor p = anchors[j]; p.BottomAnchor = bottomAnchorMax; p.TopAnchor = topAnchorMax; } }
internal static void CalculateAnchorSizes(Database database, out Anchor[] anchors, ProperLayeredGraph properLayeredGraph, GeometryGraph originalGraph, BasicGraph<Node, IntEdge> intGraph, SugiyamaLayoutSettings settings) { database.Anchors = anchors = new Anchor[properLayeredGraph.NodeCount]; for (int i = 0; i < anchors.Length; i++) anchors[i] = new Anchor(settings.LabelCornersPreserveCoefficient); //go over the old vertices for (int i = 0; i < originalGraph.Nodes.Count; i++) CalcAnchorsForOriginalNode(i, intGraph, anchors, database, settings); //go over virtual vertices foreach (IntEdge intEdge in database.AllIntEdges) if (intEdge.LayerEdges != null) { foreach (LayerEdge layerEdge in intEdge.LayerEdges) { int v = layerEdge.Target; if (v != intEdge.Target) { Anchor anchor = anchors[v]; if (!database.MultipleMiddles.Contains(v)) { anchor.LeftAnchor = anchor.RightAnchor = VirtualNodeWidth/2.0f; anchor.TopAnchor = anchor.BottomAnchor = VirtualNodeHeight(settings)/2.0f; } else { anchor.LeftAnchor = anchor.RightAnchor = VirtualNodeWidth*4; anchor.TopAnchor = anchor.BottomAnchor = VirtualNodeHeight(settings)/2.0f; } } } //fix label vertices if (intEdge.HasLabel) { int lj = intEdge.LayerEdges[intEdge.LayerEdges.Count/2].Source; Anchor a = anchors[lj]; double w = intEdge.LabelWidth, h = intEdge.LabelHeight; a.RightAnchor = w; a.LeftAnchor = VirtualNodeWidth*8; if (a.TopAnchor < h/2.0) a.TopAnchor = a.BottomAnchor = h/2.0; a.LabelToTheRightOfAnchorCenter = true; } } }
void CalcAnchorsForOriginalNode(int i) { double leftAnchor = 0; double rightAnchor = leftAnchor; double topAnchor = 0; double bottomAnchor = topAnchor; //that's what we would have without the label and multiedges if (intGraph.Nodes != null) { Node node = intGraph.Nodes[i]; ExtendStandardAnchors(ref leftAnchor, ref rightAnchor, ref topAnchor, ref bottomAnchor, node); } RightAnchorMultiSelfEdges(i, ref rightAnchor, ref topAnchor, ref bottomAnchor); double hw = LayoutSettings.MinNodeWidth / 2; if (leftAnchor < hw) leftAnchor = hw; if (rightAnchor < hw) rightAnchor = hw; double hh = LayoutSettings.MinNodeHeight / 2; if (topAnchor < hh) topAnchor = hh; if (bottomAnchor < hh) bottomAnchor = hh; anchors[i] = new Anchor(leftAnchor, rightAnchor, topAnchor, bottomAnchor, this.intGraph.Nodes[i], LayoutSettings.LabelCornersPreserveCoefficient) {Padding = this.intGraph.Nodes[i].Padding}; #if TEST_MSAGL //anchors[i].Id = this.intGraph.Nodes[i].Id; #endif }
private void SizeAnchors() { dataBase.Anchors = anchors = new Anchor[properLayeredGraph.NodeCount]; for (int i = 0; i < anchors.Length; i++) anchors[i] = new Anchor(LayoutSettings.LabelCornersPreserveCoefficient); //go over the old vertices for (int i = 0; i < intGraph.NodeCount; i++) CalcAnchorsForOriginalNode(i); //go over virtual vertices foreach (IntEdge intEdge in dataBase.AllIntEdges) { if (intEdge.LayerEdges != null) { foreach (LayerEdge layerEdge in intEdge.LayerEdges) { int v = layerEdge.Target; if (v != intEdge.Target) { Anchor anchor = anchors[v]; if (!dataBase.MultipleMiddles.Contains(v)) { anchor.LeftAnchor = anchor.RightAnchor = VirtualNodeWidth / 2.0f; anchor.TopAnchor = anchor.BottomAnchor = VirtualNodeHeight / 2.0f; } else { anchor.LeftAnchor = anchor.RightAnchor = VirtualNodeWidth * 4; anchor.TopAnchor = anchor.BottomAnchor = VirtualNodeHeight / 2.0f; } } } //fix label vertices if (intEdge.Edge.Label!=null) { int lj = intEdge.LayerEdges[intEdge.LayerEdges.Count / 2].Source; Anchor a = anchors[lj]; double w = intEdge.LabelWidth, h = intEdge.LabelHeight; a.RightAnchor = w; a.LeftAnchor = LayoutSettings.NodeSeparation; if (a.TopAnchor < h / 2.0) a.TopAnchor = a.BottomAnchor = h / 2.0; a.LabelToTheRightOfAnchorCenter = true; } } } }
/// <summary> /// /// </summary> static internal void CalculateXCoordinates(LayerArrays layerArrays, ProperLayeredGraph layeredGraph, int nOfOriginalVs, Anchor[] anchors, double nodeSeparation) { XCoordsWithAlignment x = new XCoordsWithAlignment(layerArrays, layeredGraph, nOfOriginalVs, anchors, nodeSeparation); x.Calculate(); }
///// <summary> ///// private constructor ///// </summary> ///// <param name="layerArrays"></param> ///// <param name="anchs"></param> ///// <param name="layeredGraph"></param> ///// <param name="nOfOriginalVs"></param> XCoordsWithAlignment(LayerArrays layerArrays, ProperLayeredGraph layeredGraph, int nOfOriginalVs, Anchor[] anchorsP, double ns) { this.la = layerArrays; this.graph = layeredGraph; this.nOfOriginalVertices = nOfOriginalVs; this.nOfVertices = graph.NodeCount; this.h = la.Layers.Length; this.root = new int[nOfVertices]; this.align = new int[nOfVertices]; // this.sink = new int[nOfVertices]; // this.shift = new double[nOfVertices]; this.anchors = anchorsP; this.nodeSep = ns; }
//void UpdateEdgeLabelPosition(LayerEdge[][] list, int i) { // IntEdge e; // int labelNodeIndex; // if (Engine.GetLabelEdgeAndVirtualNode(list, i, out e, out labelNodeIndex)) { // UpdateLabel(e, labelNodeIndex, db.Anchors); // } //} internal static void UpdateLabel(Edge e, Anchor anchor){ LineSegment labelSide = null; if (anchor.LabelToTheRightOfAnchorCenter){ e.Label.Center = new Point(anchor.X + anchor.RightAnchor/2, anchor.Y); labelSide = new LineSegment(e.LabelBBox.LeftTop, e.LabelBBox.LeftBottom); } else if (anchor.LabelToTheLeftOfAnchorCenter){ e.Label.Center = new Point(anchor.X - anchor.LeftAnchor/2, anchor.Y); labelSide = new LineSegment(e.LabelBBox.RightTop, e.LabelBBox.RightBottom); } ICurve segmentInFrontOfLabel = GetSegmentInFrontOfLabel(e.Curve, e.Label.Center.Y); if (segmentInFrontOfLabel == null) return; if (Curve.GetAllIntersections(e.Curve, Curve.PolyFromBox(e.LabelBBox), false).Count == 0){ Point curveClosestPoint; Point labelSideClosest; if (FindClosestPoints(out curveClosestPoint, out labelSideClosest, segmentInFrontOfLabel, labelSide)){ //shift the label if needed ShiftLabel(e, ref curveClosestPoint, ref labelSideClosest); } else{ //assume that the distance is reached at the ends of labelSideClosest double u = segmentInFrontOfLabel.ClosestParameter(labelSide.Start); double v = segmentInFrontOfLabel.ClosestParameter(labelSide.End); if ((segmentInFrontOfLabel[u] - labelSide.Start).Length < (segmentInFrontOfLabel[v] - labelSide.End).Length){ curveClosestPoint = segmentInFrontOfLabel[u]; labelSideClosest = labelSide.Start; } else{ curveClosestPoint = segmentInFrontOfLabel[v]; labelSideClosest = labelSide.End; } ShiftLabel(e, ref curveClosestPoint, ref labelSideClosest); } } }
static int DrawAnchor(Graphics g, int i, Anchor p){ string stringToShow = i + (p.UserData != null ? (" " + p.UserData) : String.Empty); DrawStringInRectCenter(g, Brushes.Blue, new Font(FontFamily.GenericSerif, 10), stringToShow, new RectangleF((float) p.Left, (float) p.Bottom, (float) p.RightAnchor + (float) p.LeftAnchor, (float) p.TopAnchor + (float) p.BottomAnchor)); i++; return i; }