GetEdgeEndpoint ( VertexDrawingHistory otherVertexDrawingHistory, out Point edgeEndpoint ) { AssertValid(); Point oVertexLocation = this.VertexLocation; // A diamond is just a rotated square, so the // VertexDrawingHistory.GetEdgePointOnRectangle() can be used if the // diamond and the other vertex location are first rotated 45 degrees // about the diamond's center. Double dHalfSquareWidth = m_dHalfWidth / Math.Sqrt(2.0); Rect oRotatedDiamond = new Rect( oVertexLocation.X - dHalfSquareWidth, oVertexLocation.Y - dHalfSquareWidth, 2.0 * dHalfSquareWidth, 2.0 * dHalfSquareWidth ); Matrix oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oVertexLocation, 45); Point oRotatedOtherVertexLocation = oMatrix.Transform(otherVertexDrawingHistory.VertexLocation); Point oRotatedEdgeEndpoint; GetEdgeEndpointOnRectangle(oVertexLocation, oRotatedDiamond, oRotatedOtherVertexLocation, out oRotatedEdgeEndpoint); // Now rotate the computed edge endpoint in the other direction. oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oVertexLocation, -45); edgeEndpoint = oMatrix.Transform(oRotatedEdgeEndpoint); }
GetEdgeEndpoint ( Point otherEndpoint, out Point edgeEndpoint ) { AssertValid(); Point oVertexLocation = this.VertexLocation; // Instead of doing geometry calculations similar to what is done in // VertexDrawingHistory.GetEdgePointOnRectangle(), make use of that // method by making the triangle look like a rectangle. First, figure // out how to rotate the triangle about the vertex location so that the // side containing the endpoint is vertical and to the right of the // vertex location. Double dEdgeAngle = WpfGraphicsUtil.GetAngleBetweenPointsRadians( oVertexLocation, otherEndpoint); Double dEdgeAngleDegrees = MathUtil.RadiansToDegrees(dEdgeAngle); Double dAngleToRotateDegrees; if (dEdgeAngleDegrees >= -30.0 && dEdgeAngleDegrees < 90.0) { dAngleToRotateDegrees = 30.0; } else if (dEdgeAngleDegrees >= -150.0 && dEdgeAngleDegrees < -30.0) { dAngleToRotateDegrees = 270.0; } else { dAngleToRotateDegrees = 150.0; } // Now create a rotated rectangle that is centered on the vertex // location and that has the vertical, endpoint-containing triangle // side as the rectangle's right edge. Double dWidth = 2.0 * m_dHalfWidth; Rect oRotatedRectangle = new Rect( oVertexLocation.X, oVertexLocation.Y - m_dHalfWidth, dWidth * WpfGraphicsUtil.Tangent30Degrees, dWidth ); Matrix oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oVertexLocation, dAngleToRotateDegrees); // Rotate the other vertex location. Point oRotatedOtherVertexLocation = oMatrix.Transform(otherEndpoint); // GetEdgeEndpointOnRectangle will compute an endpoint on the // rectangle's right edge. Point oRotatedEdgeEndpoint; GetEdgeEndpointOnRectangle(oVertexLocation, oRotatedRectangle, oRotatedOtherVertexLocation, out oRotatedEdgeEndpoint); // Now rotate the edge endpoint in the other direction. oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oVertexLocation, -dAngleToRotateDegrees); edgeEndpoint = oMatrix.Transform(oRotatedEdgeEndpoint); }
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]); }