/// <summary> /// Adjusts the edge end points so they don't end outside the shape of the node they are attached to. /// </summary> private static void AdjustPortLocation(LayoutGraph graph, Edge e, YPointPath path, bool atSource) { Node node = atSource ? e.Source : e.Target; YPoint pointRel = atSource ? graph.GetSourcePointRel(e) : graph.GetTargetPointRel(e); // get offset from the node center to the end of the shape at the node side the edge connects to LineSegment segment = path.GetLineSegment(atSource ? 0 : path.Length() - 2); double offset = Math.Min(graph.GetWidth(node), graph.GetHeight(node)) / 2; double offsetX = segment.DeltaX > 0 ^ atSource ? -offset : offset; double offsetY = segment.DeltaY > 0 ^ atSource ? -offset : offset; // if the edge end point is at the center of this side, we use the calculated offset to put the end point on // the node bounds, otherwise we prolong the last segment to the center line of the node so it doesn't end // outside the node's shape YPoint newPortLocation = segment.IsHorizontal ? new YPoint(pointRel.Y != 0 ? 0 : offsetX, pointRel.Y) : new YPoint(pointRel.X, pointRel.X != 0 ? 0 : offsetY); if (atSource) { graph.SetSourcePointRel(e, newPortLocation); } else { graph.SetTargetPointRel(e, newPortLocation); } }
private void AdjustNodeSize(Node node, LayoutGraph graph) { double width = 60; double height = 40; var leftEdgeSpace = CalcRequiredSpace(node.InEdges, graph); var rightEdgeSpace = CalcRequiredSpace(node.OutEdges, graph); if (LayoutOrientation == LayoutOrientation.TopToBottom || LayoutOrientation == LayoutOrientation.BottomToTop) { // we have to enlarge the width such that the in-/out-edges can be placed side by side without overlaps width = Math.Max(width, leftEdgeSpace); width = Math.Max(width, rightEdgeSpace); } else { // we have to enlarge the height such that the in-/out-edges can be placed side by side without overlaps height = Math.Max(height, leftEdgeSpace); height = Math.Max(height, rightEdgeSpace); } // adjust size for edges with strong port constraints var edgeThicknessDP = graph.GetDataProvider(HierarchicLayout.EdgeThicknessDpKey); if (edgeThicknessDP != null) { foreach (var edge in node.Edges) { var thickness = edgeThicknessDP.GetDouble(edge); var spc = PortConstraint.GetSPC(graph, edge); if (edge.Source == node && spc != null && spc.Strong) { var sourcePoint = graph.GetSourcePointRel(edge); width = Math.Max(width, Math.Abs(sourcePoint.X) * 2 + thickness); height = Math.Max(height, Math.Abs(sourcePoint.Y) * 2 + thickness); } var tpc = PortConstraint.GetTPC(graph, edge); if (edge.Target == node && tpc != null && tpc.Strong) { var targetPoint = graph.GetTargetPointRel(edge); width = Math.Max(width, Math.Abs(targetPoint.X) * 2 + thickness); height = Math.Max(height, Math.Abs(targetPoint.Y) * 2 + thickness); } } } graph.SetSize(node, width, height); }
/// <inheritdoc/> public virtual double GetProfit(LabelCandidate candidate) { if (candidate.Owner is IEdgeLabelLayout) { return(1); } double profit = 0; INodeLabelLayout nl = (INodeLabelLayout)candidate.Owner; var node = graph.GetOwner(nl); var nodeLayout = graph.GetLayout(node); var candidateLayout = candidate.BoundingBox; var isLeft = candidateLayout.X + candidateLayout.Width / 2 < nodeLayout.X; var isRight = candidateLayout.X + candidateLayout.Width / 2 > (nodeLayout.X + nodeLayout.Width); var isTop = candidateLayout.Y + candidateLayout.Height / 2 < nodeLayout.Y; var isBottom = candidateLayout.Y + candidateLayout.Height / 2 > (nodeLayout.Y + nodeLayout.Height); var horizontalCenter = !isLeft && !isRight; var verticalCenter = !isTop && !isBottom; if (horizontalCenter && verticalCenter) { // candidate is in center -> don't use return(0); } else if (horizontalCenter || verticalCenter) { profit = 0.95; } else { // diagonal candidates get a bit less profit profit = 0.9; } foreach (var edge in node.Edges) { var portLocation = edge.Source == node?graph.GetSourcePointRel(edge) : graph.GetTargetPointRel(edge); if (Math.Abs(portLocation.X) > Math.Abs(portLocation.Y)) { // edge at left or right if (portLocation.X < 0 && isLeft || portLocation.X > 0 && isRight) { if (isTop || isBottom) { profit -= 0.03; } else { // edge at same side as candidate profit -= 0.2; } } else if (horizontalCenter) { // candidate is close to the edge but not on the same side profit -= 0.01; } } else { // edge at top or bottom if (portLocation.Y < 0 && isTop || portLocation.Y > 0 && isBottom) { if (isLeft || isRight) { profit -= 0.03; } else { profit -= 0.2; } } else if (verticalCenter) { // candidate is close to the edge but not on the same side profit -= 0.01; } } } return(Math.Max(0, profit)); }