/// <summary> /// Draws a partially defined graph edge</summary> /// <param name="fromNode">Source node, or null</param> /// <param name="fromRoute">Source route, or null</param> /// <param name="toNode">Destination node, or null</param> /// <param name="toRoute">Destination route, or null</param> /// <param name="label">Edge label</param> /// <param name="endPoint">Endpoint to substitute for source or destination (in client coords), if either is null</param> /// <param name="g">Graphics object</param> public override void Draw( TNode fromNode, NumberedRoute fromRoute, TNode toNode, NumberedRoute toRoute, string label, Point endPoint, D2dGraphics g) { var inverse = g.Transform; inverse.Invert(); PointF end = Matrix3x2F.TransformPoint(inverse, endPoint); TNode node = (fromNode != null) ? fromNode : toNode; CircleF boundary = GetBoundary(node); Vec2F proj = new Vec2F(); if (CircleF.Project(new Vec2F(end), boundary, ref proj)) { PointF start = new PointF(proj.X, proj.Y); g.DrawLine(start, end, m_theme.OutlineBrush); if (fromNode == null) { PointF temp = end; end = start; start = temp; } Vec2F endTangent = new Vec2F(end.X - start.X, end.Y - start.Y); Vec2F arrowPosition = new Vec2F(end); DrawArrow(arrowPosition, endTangent, m_theme.OutlineBrush, g); if (!string.IsNullOrEmpty(label)) { PointF textPoint = new PointF((end.X + start.X) * 0.5f, (end.Y + start.Y) * 0.5f); RectangleF textBox = new RectangleF(textPoint.X - 512, textPoint.Y, 1024, m_theme.TextFormat.FontHeight); //g.DrawString(label, m_theme.Font, m_theme.TextBrush, textBox, m_theme.CenterStringFormat); g.DrawText(label, m_theme.TextFormat, textBox, m_theme.TextBrush); } } }
/// <summary> /// Finds node and/or edge hit by the given point</summary> /// <param name="graph">Graph to test</param> /// <param name="priorityEdge">Graph edge to test before others</param> /// <param name="p">Point to test in graph space</param> /// <param name="g">D2dGraphics object</param> /// <returns>Hit record containing node and/or edge hit by the given point</returns> public override GraphHitRecord <TNode, TEdge, NumberedRoute> Pick( IGraph <TNode, TEdge, NumberedRoute> graph, TEdge priorityEdge, PointF p, D2dGraphics g) { TNode pickedNode = null; TEdge pickedEdge = null; NumberedRoute fromRoute = null; NumberedRoute toRoute = null; Vec2F v = new Vec2F(p.X, p.Y); if (priorityEdge != null && Pick(priorityEdge, v)) { pickedEdge = priorityEdge; } else { foreach (TEdge edge in graph.Edges.Reverse()) { if (Pick(edge, v)) { pickedEdge = edge; break; } } } foreach (TNode node in graph.Nodes.Reverse()) { if (Pick(node, p)) { pickedNode = node; CircleF boundary = GetBoundary(node); boundary.Radius -= m_theme.PickTolerance; bool onEdge = !boundary.Contains(v); if (pickedEdge == null) { if (onEdge) { // edge of node can be source or destination fromRoute = new NumberedRoute(); toRoute = new NumberedRoute(); } } else // hit on edge and node { if (onEdge) { if (pickedEdge.FromNode == pickedNode) { fromRoute = new NumberedRoute(); } else if (pickedEdge.ToNode == pickedNode) { toRoute = new NumberedRoute(); } } } break; } } var result = new GraphHitRecord <TNode, TEdge, NumberedRoute>(pickedNode, pickedEdge, fromRoute, toRoute); PointF clientP = Matrix3x2F.TransformPoint(g.Transform, p); if (fromRoute != null) { result.FromRoutePos = clientP; } if (toRoute != null) { result.ToRoutePos = clientP; } if (pickedNode != null && pickedEdge == null) { // label is centered in entire node RectangleF labelBounds = GetBounds(pickedNode, g); float dHeight = labelBounds.Height - m_theme.TextFormat.FontHeight; labelBounds = new RectangleF( labelBounds.X, labelBounds.Y + dHeight / 2, labelBounds.Width, labelBounds.Height - dHeight); if (labelBounds.Contains(p)) { DiagramLabel label = new DiagramLabel( Rectangle.Truncate(labelBounds), TextFormatFlags.SingleLine | TextFormatFlags.HorizontalCenter); return (new GraphHitRecord <TNode, TEdge, NumberedRoute>(pickedNode, label)); } } else if (pickedEdge != null) { RectangleF labelBounds = GetLabelBounds(pickedEdge, g); DiagramLabel label = new DiagramLabel( Rectangle.Truncate(labelBounds), TextFormatFlags.SingleLine | TextFormatFlags.HorizontalCenter); if (labelBounds.Contains(p)) { return (new GraphHitRecord <TNode, TEdge, NumberedRoute>(pickedEdge, label)); } } return(result); }