2014-12-05 2 views
2

Я сейчас читаю Функциональное программирование в реальном мире: с примерами в F # и C# от Tomas Petricek и Jon Skeet. Я немного озадачен конкретным примером, в котором мы создаем приложение, которое отображает круговую диаграмму с некоторой статистикой популяций вместе с метками.F # разъяснение при создании меток для круговой диаграммы

Теперь это часть рисования метки или, скорее, установка координат ярлыка, который меня смущает. Я надеюсь, что автор не против, что я прикладываю выдержку здесь, но было бы сложно получить разъяснения по коду, не показывая его.

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 определяют некоторый стандарт «смещение» от центра поверхности рисунка, и я предполагаю, что тригонометрические функции определяют угол метки, потому что если я опускаю те, то все метки помещенный поверх каждого другого в нижнем правом углу. Но я не совсем понимаю , как это работает. Что именно здесь происходит?

ответ

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)) 
+0

Благодаря кучу, это было очень хорошее объяснение! –

Смежные вопросы