| netlib.narod.ru | < Назад | Оглавление | Далее > |
Запрограммировать синусоиду довольно просто, поскольку ее значения y являются простой функцией x. Однако вообще программирование кривых сложнее. Например, уравнение единичной окружности (т.е. окружности с радиусом 1), с центром в начале координат обычно дают как:
x2 + y2 = 1
В более общем виде окружность с радиусом r может быть представлена как:
x2 + y2 = r2
Но если попытаться представить это уравнение в виде зависимости y от x, то вот что получится:
y = ±√ r2 – x2
Здесь возникает целый ряд проблем. Во-первых, каждому значению x соответствуют пара значений y. Во-вторых, некоторые значения x недопустимы: x должен быть в интервале от –r до +r. И в-третьих, проблема практического толка возникает собственно при рисовании окружности на основе этого уравнения. Полученная функция нелинейна: при значениях x, близких к 0, изменения x дают относительно небольшие изменения y. Когда же x приближается к r или –r, изменения x дают гораздо большие изменения y.
Более общий подход к рисованию кривых применяет параметрические уравнения, в которых обе координаты каждой точки, x и y, вычисляются на основе значения третьей переменной, часто называемой t Интуитивно t можно воспринимать как время или какой-то абстрактный показатель, нужный для исчерпывающего определения кривой. При программировании графики в Windows Forms можно считать, что переменная t изменяется от 0 до числа на единицу меньшего, чем количество структур PointF в массиве.
Параметрические уравнения, определяющие единичную окружность, таковы:
x(t) = cos(t)
y(t) = sin(t)
Для t, изменяющегося от 0 до 2π радиан, эти уравнения задают окружность с центром в точке с координатами (0, 0) и радиусом 1.
Сходным образом может быть задан и эллипс:
x(t) = RX cos(t)
y(t) = RY sin(t)
Оси эллипса параллельны горизонтальной и вертикальной осям координат. Длина горизонтальной оси эллипса равна 2 × RX, вертикальной — 2 × RY. Эллипс также центрирован относительно начала координат. Чтобы переместить центр эллипса в точку с координатами (CX, CY), формулы должны принять такой вид:
x(t) = CX + RX cos(t)
y(t) = CY + RY sin(t)
А вот программа для рисования эллипса, вписанного в экран:
PolyEllipse.cs
//--------------------------------------------
// PolyEllipse.cs (C) 2001 by Charles Petzold
//--------------------------------------------
using System;
using System.Drawing;
using System.Windows.Forms;
class PolyEllipse: PrintableForm
{
public new static void Main()
{
Application.Run(new PolyEllipse());
}
public PolyEllipse()
{
Text = "Ellipse with DrawLines";
}
protected override void DoPage(Graphics grfx, Color clr, int cx, int cy)
{
int iNum = 2 * (cx + cy);
PointF[] aptf = new PointF[iNum];
for (int i = 0; i < iNum; i++)
{
double dAng = i * 2 * Math.PI / (iNum - 1);
aptf[i].X = (cx - 1) / 2f * (1 + (float)Math.Cos(dAng));
aptf[i].Y = (cy - 1) / 2f * (1 + (float)Math.Sin(dAng));
}
grfx.DrawLines(new Pen(clr), aptf);
}
}
Поскольку центр эллипса находится на пересечении прямых, делящих экран надвое по ширине и высоте, а ширина и высота эллипса равны ширине и высоте области экрана, я смог несколько упростить формулы. Я аппроксимировал число точек массива как число точек, достаточное для изображения прямоугольника, периметр которого равен периметру экрана.

Далее вы увидите, что в классе Graphics есть метод DrawEllipse. Возникает вопрос: зачем было рисовать эллипс «вручную»? Назовем это просто упражнением для подготовки к изучению следующей программы, рисующей фигуру, простого метода для изображения которой точно нет в классе Graphics.
Spiral.cs
//---------------------------------------
// Spiral.cs (C) 2001 by Charles Petzold
//---------------------------------------
using System;
using System.Drawing;
using System.Windows.Forms;
class Spiral: PrintableForm
{
public new static void Main()
{
Application.Run(new Spiral());
}
public Spiral()
{
Text = "Spiral";
}
protected override void DoPage(Graphics grfx, Color clr, int cx, int cy)
{
const int iNumRevs = 20;
int iNumPoints = iNumRevs * 2 * (cx + cy);
PointF[] aptf = new PointF[iNumPoints];
float fAngle, fScale;
for (int i = 0; i < iNumPoints; i++)
{
fAngle = (float)(i * 2 * Math.PI /(iNumPoints / iNumRevs));
fScale = 1 - (float)i / iNumPoints;
aptf[i].X = (float)(cx / 2 * (1 + fScale * Math.Cos(fAngle)));
aptf[i].Y = (float)(cy / 2 * (1 + fScale * Math.Sin(fAngle)));
}
grfx.DrawLines(new Pen(clr), aptf);
}
}
А вот как выглядит эта фигура:

| netlib.narod.ru | < Назад | Оглавление | Далее > |