/// <summary> /// Generates a path for the callout decoration, which is an isosceles triangle from the label's center pointing /// to the node. /// </summary> /// <param name="label">The label for which to create the path.</param> /// <returns>A path for the callout triangle.</returns> private static GeneralPath GenerateTrianglePath(ILabel label) { var node = (INode)label.Owner; var layout = label.GetLayout(); // Find the point where the triangle attaches to the outline shape var outlineShape = node.Style.Renderer.GetShapeGeometry(node, node.Style).GetOutline(); var nodeCenter = node.Layout.GetCenter(); var labelCenter = layout.GetCenter(); if (outlineShape == null) { outlineShape = new GeneralPath(4); outlineShape.AppendOrientedRectangle(layout, false); } var intersection = outlineShape.FindLineIntersection(nodeCenter, labelCenter); var intersectionPoint = nodeCenter + intersection * (labelCenter - nodeCenter); // Find the vector that is orthogonal to the line connecting the label and node centers var triangleVector = labelCenter - intersectionPoint; var orthoVector = OrthoNormal(triangleVector); // Construct the other points of the triangle var point2 = labelCenter + orthoVector * 20; var point3 = labelCenter - orthoVector * 20; // Create the path var p = new GeneralPath(); p.MoveTo(intersectionPoint); p.LineTo(point2); p.LineTo(point3); p.Close(); return(p); }