Smrf.NodeXL.Visualization.Wpf.EdgeDrawer.DrawBezierLabel C# (CSharp) Method

DrawBezierLabel() protected method

protected DrawBezierLabel ( System.Windows.Media.DrawingContext oDrawingContext, GraphDrawingContext oGraphDrawingContext, System.Windows.Media.FormattedText oFormattedText, Point oEdgeEndpoint1, Point oEdgeEndpoint2, System.Windows.Media.PathGeometry oBezierCurve, Double dLabelOriginAsFractionOfEdgeLength, Double dEdgeLength, Double dBufferWidth, Color oLabelTextColor, Color oTranslucentRectangleColor, Double dFontSize ) : void
oDrawingContext System.Windows.Media.DrawingContext
oGraphDrawingContext GraphDrawingContext
oFormattedText System.Windows.Media.FormattedText
oEdgeEndpoint1 Point
oEdgeEndpoint2 Point
oBezierCurve System.Windows.Media.PathGeometry
dLabelOriginAsFractionOfEdgeLength Double
dEdgeLength Double
dBufferWidth Double
oLabelTextColor Color
oTranslucentRectangleColor Color
dFontSize Double
return void
    DrawBezierLabel
    (
        DrawingContext oDrawingContext,
        GraphDrawingContext oGraphDrawingContext,
        FormattedText oFormattedText,
        Point oEdgeEndpoint1,
        Point oEdgeEndpoint2,
        PathGeometry oBezierCurve,
        Double dLabelOriginAsFractionOfEdgeLength,
        Double dEdgeLength,
        Double dBufferWidth,
        Color oLabelTextColor,
        Color oTranslucentRectangleColor,
        Double dFontSize
    )
    {
        Debug.Assert(oDrawingContext != null);
        Debug.Assert(oGraphDrawingContext != null);
        Debug.Assert(oFormattedText != null);
        Debug.Assert(oBezierCurve != null);
        Debug.Assert(dLabelOriginAsFractionOfEdgeLength >= 0);
        Debug.Assert(dEdgeLength >= 0);
        Debug.Assert(dBufferWidth >= 0);
        Debug.Assert(dFontSize > 0);
        AssertValid();

        // This method uses a modified version of the technique described in
        // "Render Text On A Path With WPF," by Charles Petzold, at
        // http://msdn.microsoft.com/en-us/magazine/dd263097.aspx.

        if (oEdgeEndpoint2.X < oEdgeEndpoint1.X)
        {
            // Don't let text be drawn upside-down.

            WpfGraphicsUtil.SwapPoints(ref oEdgeEndpoint1, ref oEdgeEndpoint2);

            oBezierCurve = WpfPathGeometryUtil.ReverseQuadraticBezierCurve(
                oBezierCurve);
        }

        Double dTextWidth = oFormattedText.Width;
        Double dTextWidthToEdgeLengthRatio = dTextWidth / dEdgeLength;

        Double dLineOffset = 0;
        Point oOrigin = new Point(0, 0);

        String [] asLines =
            oFormattedText.Text.Split( new char[] {'\r', '\n'} );

        foreach (String sLine in asLines)
        {
            // The label characters will be drawn one by one using positions
            // computed by PathGeometry.GetPointAtFractionLength().  The first
            // character will be at dLabelOriginAsFractionOfEdgeLength.

            Double dFractionOfEdgeLength = dLabelOriginAsFractionOfEdgeLength;

            Boolean bUsedEllipses = false;

            foreach (Char c in sLine)
            {
                if (bUsedEllipses)
                {
                    break;
                }

                Point oPointAtFractionLength;
                Point oPointTangent;

                oBezierCurve.GetPointAtFractionLength(dFractionOfEdgeLength,
                    out oPointAtFractionLength, out oPointTangent);

                Double dCharacterAngleDegrees = MathUtil.RadiansToDegrees(
                    Math.Atan2(oPointTangent.Y, oPointTangent.X) );

                String sChar = c.ToString();

                if ( (oPointAtFractionLength - oEdgeEndpoint2).Length <=
                    6.0 * dBufferWidth)
                {
                    // There is probably not enough room for the rest of the
                    // string.  Terminate it with ellipses.  (The buffer width
                    // multiple was determined experimentally.)

                    bUsedEllipses = true;
                    sChar = "...";
                }

                FormattedText oCharacterFormattedText =
                    m_oFormattedTextManager.CreateFormattedText(
                        sChar, oLabelTextColor, dFontSize, m_dGraphScale);

                Double dCharacterWidth =
                    oCharacterFormattedText.WidthIncludingTrailingWhitespace;

                Double dCharacterHeight = oCharacterFormattedText.Height;

                // Apply a RotateTransform to make the character's base
                // approximately parallel to the Bezier curve's tangent, and a
                // TranslateTransform to vertically position the character.

                oDrawingContext.PushTransform( new TranslateTransform(
                    oPointAtFractionLength.X,

                    oPointAtFractionLength.Y - (oFormattedText.Height / 2.0)
                        + dLineOffset
                    ) );

                oDrawingContext.PushTransform( new RotateTransform(
                    dCharacterAngleDegrees, 0,
                    (oFormattedText.Height / 2.0) - dLineOffset
                    ) );

                // A translucent rectangle is drawn for each character.
                // Rounding errors cause the underlying edge to show through
                // faintly between the rectangles, which is a bug.  How to fix
                // this?

                Rect oTranslucentRectangle = new Rect( oOrigin,
                    new Size(dCharacterWidth, dCharacterHeight) );

                DrawTranslucentRectangle(oDrawingContext,
                    oTranslucentRectangle, oTranslucentRectangleColor);

                oDrawingContext.DrawText(oCharacterFormattedText, oOrigin);

                oDrawingContext.Pop();
                oDrawingContext.Pop();

                dFractionOfEdgeLength += dCharacterWidth / dEdgeLength;
            }

            dLineOffset += oFormattedText.Height / asLines.Length;
        }
    }