Нарисуйте анимированный эпитрохоид в C#

В этом примере показан один из способов рисования анимированного эпитрохоида. (См. Пример Нарисуйте эпитрохоид в C# для объяснения того, как нарисуйте эпитрохоид.) Эта программа генерирует все точки, необходимые для рисования полной кривой. Затем каждый раз, когда срабатывает его Timer, он набирает точки до определенной позиции в списке точек. Чтобы нарисовать круги, которые генерируют кривую, он также сохраняет углы, которые используются для генерации точек.

Программа использует следующий код для сохранения точек и углов.

// Точки кривой.
private PointF[] Points = null;
private float[] Thetas = null;
...
// Делаем точки кривой.
private void MakeEpitrochoidPoints(
    float a, float b, float h, float dt)
{
    // Вычислить значение остановки для t.
    float stop_t = (float)(b * 2 * Math.PI);

    // Найти точки.
    List point_list = new List();
    List theta_list = new List();

    point_list.Add(new PointF(X(a, b, h, 0), Y(a, b, h, 0)));
    theta_list.Add(0);
    for (float t = dt; t <= stop_t; t += dt)
    {
        point_list.Add(new PointF(X(a, b, h, t), Y(a, b, h, t)));
        theta_list.Add(t);
    }
    point_list.Add(new PointF(X(a, b, h, 0), Y(a, b, h, 0)));
    theta_list.Add(0);

    Points = point_list.ToArray();
    Thetas = theta_list.ToArray();
}

// Параметрическая функция X (t).
private float X(float a, float b, float h, float t)
{
    return (float)((a + b) * Math.Cos(t) -
        h * Math.Cos(t * (a + b) / b));
}

// Параметрическая функция Y (t).
private float Y(float a, float b, float h, float t)
{
    return (float)((a + b) * Math.Sin(t) -
        h * Math.Sin(t * (a + b) / b));
}

Метод MakeEpitrochoidPoints вычисляет значения угла, который он должен пересечь, чтобы нарисовать всю кривую. Затем он перебирает эти значения, сохраняя точки кривой и углы в списках. Он заканчивается путем преобразования списков в массивы.

Методы X и Y - это параметрические функции, которые генерируют кривую.

Следующий код показывает, как программа рисует кривую.

// Нарисуем еще одну точку.
private void tmrDraw_Tick(object sender, EventArgs e)
{
    MaxPointToDraw++;
    if (MaxPointToDraw >= Points.Length - 1)
    {
        tmrDraw.Enabled = false;
        Cursor = Cursors.Default;
    }
    picCanvas.Refresh();
}

// Рисуем эпитрохоид.
private void picCanvas_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.Clear(picCanvas.BackColor);
    if (Points == null) return;

    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

    // Масштаб и центр.
    float scale = Math.Min(
        picCanvas.ClientSize.Width * 0.45f,
        picCanvas.ClientSize.Height * 0.45f);
    e.Graphics.ScaleTransform(
        scale / (a + b + h), scale / (a + b + h));
    e.Graphics.TranslateTransform(
        picCanvas.ClientSize.Width / 2,
        picCanvas.ClientSize.Height / 2,
        MatrixOrder.Append);

    // Нарисуем круги.
    using (Pen black_pen = new Pen(Color.Black, 0))
    {
        // Внутренний круг.
        e.Graphics.DrawEllipse(black_pen, -a, -a, 2 * a, 2 * a);

        // Внешняя окружность.
        float theta = Thetas[MaxPointToDraw];
        float cx = (float)((a + b) * Math.Cos(theta));
        float cy = (float)((a + b) * Math.Sin(theta));

        e.Graphics.DrawEllipse(black_pen,
            cx - b, cy - b, 2 * b, 2 * b);

        // Линейный сегмент.
        e.Graphics.DrawLine(black_pen, cx, cy,
            Points[MaxPointToDraw].X, Points[MaxPointToDraw].Y);
    }

    // Рисуем кривую.
    using (Pen white_pen = new Pen(Color.White, 0))
    {
        for (int i = 0; i < MaxPointToDraw; i++)
        {
            e.Graphics.DrawLine(white_pen,
                Points[i], Points[i + 1]);
        }
    }
}

Когда срабатывает Timer, он увеличивает MaxPointToDraw, чтобы нарисовать другую точку, а затем обновляет picCanvas PictureBox.

Источник: http://csharphelper.com/blog/2014/11/draw-an-animated-epitrochoid-in-c/

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Adblock
detector