关于为饼图创建标签的F#说明

时间:2014-12-05 13:58:50

标签: winforms f# trigonometry pie-chart

我目前正在阅读真实世界的功能编程:使用Tomas Petricek和Jon Skeet的F#和C#中的示例。我对一个特殊的例子感到有些困惑,我们生成一个应用程序,显示一个包含一些人口统计信息和标签的饼图。

现在它是绘制标签的一部分,或者更确切地说是设置我感到困惑的标签的坐标。我希望作者不介意我在这里附上摘录,但如果没有显示它就很难澄清代码。

let centerX, centerY = 300.0, 200.0
let labelDistance = 150.0

let drawLabel (gr: Graphics) title startAngle angle = 
    let lblAngle = float(startAngle + angle / 2)
    let ra = Math.PI * 2.0 * lblAngle / 360.0
    let x = centerX + labelDistance * cos(ra)
    let y = centerY + labelDistance * sin(ra)
    let size = gr.MeasureString(title, fnt)
    let rc = new PointF(float32(x) - size.Width / 2.0f,
                        float32(y) - size.Height / 2.0f)
    gr.DrawString(title, fnt, Brushes.Black, new RectangleF(rc, size))

似乎labelDistancecenterX, centerY定义了一些标准"偏移"从绘图表面的中心开始,我猜测三角函数定义了标签的角度,因为如果省略那些,则所有标签都放在右下角的顶部。但我不太明白 这是如何运作的。这到底发生了什么?

1 个答案:

答案 0 :(得分:3)

通过添加评论来实现这一点,不一定按此顺序解决:

// startAngle is the angle in degrees of this segment, angle is the angle of
// the segment itself.
let drawLabel (gr: Graphics) title startAngle angle = 
    // So this is the angle of the centre of this segment.
    let lblAngle = float(startAngle + angle / 2)
    // And ra is the same angle, now in radians.
    let ra = Math.PI * 2.0 * lblAngle / 360.0
    // So these work out the position of the label in the usual
    // way, using cosine(angle-in-radians) and then scaling for the X
    // and using sine for the Y. Both relative to the centre of the
    // circle.
    let x = centerX + labelDistance * cos(ra)
    let y = centerY + labelDistance * sin(ra)
    // How long, in pixels, is the text?
    let size = gr.MeasureString(title, fnt)
    // Create an instance of the right data structure adjusting
    // so the calculated point is the centre of the rectangle
    // in which the text will be drawn.
    let rc = new PointF(float32(x) - size.Width / 2.0f,
                        float32(y) - size.Height / 2.0f)
    // And, thus, we can now draw the text.
    gr.DrawString(title, fnt, Brushes.Black, new RectangleF(rc, size))