我目前正在阅读真实世界的功能编程:使用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))
似乎labelDistance
和centerX, centerY
定义了一些标准"偏移"从绘图表面的中心开始,我猜测三角函数定义了标签的角度,因为如果省略那些,则所有标签都放在右下角的顶部。但我不太明白 这是如何运作的。这到底发生了什么?
答案 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))