DrawArrow ( DrawingContext oDrawingContext, Point oArrowTipLocation, Double dArrowAngle, Color oColor, Double dEdgeWidth ) { Debug.Assert(oDrawingContext != null); Debug.Assert(dEdgeWidth > 0); AssertValid(); // Compute the arrow's dimensions. The width factor is arbitrary and // was determined experimentally. const Double WidthFactor = 1.5; Double dArrowTipX = oArrowTipLocation.X; Double dArrowTipY = oArrowTipLocation.Y; Double dArrowWidth = WidthFactor * dEdgeWidth * m_dRelativeArrowSize; Double dArrowHalfHeight = dArrowWidth / 2.0; Double dX = dArrowTipX - dArrowWidth; // Compute the arrow's three points as if the arrow were at an angle of // zero degrees, then use a rotated transform to adjust for the actual // specified angle. Point [] aoPoints = new Point [] { // Index 0: Arrow tip. oArrowTipLocation, // Index 1: Arrow bottom. new Point(dX, dArrowTipY - dArrowHalfHeight), // Index 2: Arrow top. new Point(dX, dArrowTipY + dArrowHalfHeight), // Index 3: Center of the flat end of the arrow. // // Note: The 0.2 is to avoid a gap between the edge endcap and the // flat end of the arrow, but it sometimes causes the two to // overlap slightly, and that can show if the edge isn't opaque. // What is the correct way to get the endcap to merge invisibly // with the arrow? new Point(dX + 0.2, dArrowTipY) }; Matrix oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oArrowTipLocation, -MathUtil.RadiansToDegrees(dArrowAngle)); oMatrix.Transform(aoPoints); PathGeometry oArrow = WpfGraphicsUtil.PathGeometryFromPoints( aoPoints[0], aoPoints[1], aoPoints[2]); oDrawingContext.DrawGeometry(GetBrush(oColor), null, oArrow); return(aoPoints[3]); }