`private static void DrawArrowHead(Canvas canvas, PathGeometry linePath, Rect shapeRect, Color color)`

{

// Get the intersection point of the imaginary, slightly

// larger rectangle that surrounds the targer shape.

Rect outerRect = new Rect(shapeRect.Left - 10, shapeRect.Top - 10, shapeRect.Width + 20, shapeRect.Height + 20);

RectangleGeometry shapeGeometry = new RectangleGeometry(shapeRect);

Point[] intersectPoints = GetIntersectionPoints(linePath, shapeGeometry);

double innerLeft = intersectPoints[0].X;

double innerTop = intersectPoints[0].Y;

shapeGeometry = new RectangleGeometry(outerRect);

intersectPoints = GetIntersectionPoints(linePath, shapeGeometry);

double outerLeft = intersectPoints[0].X;

double outerTop = intersectPoints[0].Y;

Polygon arrowHead = new Polygon();

arrowHead.Points = new PointCollection();

arrowHead.Points.Add(new Point(innerLeft, innerTop));

arrowHead.Points.Add(new Point(innerLeft + 10, innerTop + 5));

arrowHead.Points.Add(new Point(innerLeft + 10, innerTop - 5));

arrowHead.Points.Add(new Point(innerLeft, innerTop));

arrowHead.Stroke = new SolidColorBrush(color);

arrowHead.Fill = new SolidColorBrush(color);

// The differences between the intersection points on

// the inner and outer shapes gives us the base and

// perpendicular of the right-angled triangle

double baseSize = innerLeft - outerLeft;

double perpSize = innerTop - outerTop;

// Calculate the angle in degrees using ATan

double angle = Math.Atan(perpSize / baseSize) * 180 / Math.PI;

// Rotate another 180 degrees for lines in the 3rd & 4th quadrants

if (baseSize >= 0) angle += 180;

// Apply the rotation to the arrow head

RotateTransform rt = new RotateTransform(angle, innerLeft, innerTop);

arrowHead.RenderTransform = rt;

// Arrow heads are drawn over the lines but

// under the shapes

Canvas.SetZIndex(arrowHead, (int)Layer.Arrow);

canvas.Children.Add(arrowHead);

}

5 years ago