| netlib.narod.ru | < Назад | Оглавление | Далее > |
Кривая Безье уникально определяется четырьмя точками, которые можно обозначить p0, p1, p2 и p3. Кривая начинается в точке p0 и кончается в точке p3 поэтому p0 обычно называют начальной точкой, а p3 — конечной (в совокупности их часто называют конечными), а p1 и p2 — управляющими. Управляющие точки действуют на кривую, как магниты «притягивая» ее к себе. Вот пример кривой Безье:

Обратите внимание, что кривая, начавшись в точке p0, направляется к p1, но, не дойдя до нее, сворачивает и идет уже в сторону p2. Не касаясь p2 кривая продолжает свой путь и оканчивается в точке p3. А вот еще одна кривая Безье:

Кривая походит через две управляющие точки лишь в очень редких случаях. Например, если расположить обе управляющих точки на отрезке, соединяющем конечные точки, то кривая Безье превратится в прямую, проходящую через управляющие точки:

Возможна и другая крайность. Если расположить управляющие точки определенным образом, кривая Безье образует петлю:

Чтобы нарисовать кривую Безье в программе Windows Forms, нужно задать четыре точки структурами Point, PointF или восемью значения типа float:
Методы DrawBezier класса Graphics
| void DrawBezier(Pen pen, Point pt0, Point pt1, Point pt2, Point pt3) |
| void DrawBezier(Pen pen, PointF ptf0, PointF ptf1, PointF ptf2, PointF ptf3) |
| void DrawBezier(Pen pen, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) |
Иногда удобнее задать эти четыре точки в виде массива структур Point или PointF — этот прием поддерживают методы DrawBeziers (обратите внимание на множественное число в названии метода). Можно передать методу DrawBeziers массив из четырех структур Point или PointF. Этот метод также позволяет нарисовать несколько соединенных кривых Безье:
Методы DrawBeziers класса Graphics
| void DrawBeziers(Pen pen, Point[] apt) |
| void DrawBeziers(Pen pen, PointF[] aptf) |
При рисовании нескольких соединенных кривых Безье конечная точка одной кривой одновременно является начальной точкой следующей. Это значит, что для рисования каждой дополнительной кривой достаточно задать три новых точки. Чтобы нарисовать N кривых Безье, в массиве должно быть 3N + 1 элементов. Если число элементов массива не равно 3N + 1, то при N ≥ 1 метод генерирует исключение.
Методов FillBezier и FillBeziers не существует. Чтобы залить область, ограниченную кривыми Безье, применяются графические контуры, о которых пойдет речь в главе 15.
Чтобы почувствовать поведение кривых Безье, поэкспериментируйте с такой программой:
Bezier.cs
//---------------------------------------
// Bezier.cs (C) 2001 by Charles Petzold
//---------------------------------------
using System;
using System.Drawing;
using System.Windows.Forms;
class Bezier: Form
{
protected Point[] apt = new Point[4];
public static void Main()
{
Application.Run(new Bezier());
}
public Bezier()
{
Text = "Bezier (Mouse Defines Control Points)";
BackColor = SystemColors.Window;
ForeColor = SystemColors.WindowText;
ResizeRedraw = true;
OnResize(EventArgs.Empty);
}
protected override void OnResize(EventArgs ea)
{
base.OnResize(ea);
int cx = ClientSize.Width;
int cy = ClientSize.Height;
apt[0] = new Point( cx / 4, cy / 2);
apt[1] = new Point( cx / 2, cy / 4);
apt[2] = new Point( cx / 2, 3 * cy / 4);
apt[3] = new Point(3 * cx / 4, cy / 2);
}
protected override void OnMouseDown(MouseEventArgs mea)
{
Point pt;
if (mea.Button == MouseButtons.Left)
pt = apt[1];
else if (mea.Button == MouseButtons.Right)
pt = apt[2];
else
return;
Cursor.Position = PointToScreen(pt);
}
protected override void OnMouseMove(MouseEventArgs mea)
{
if (mea.Button == MouseButtons.Left)
{
apt[1] = new Point(mea.X, mea.Y);
Invalidate();
}
else if (mea.Button == MouseButtons.Right)
{
apt[2] = new Point(mea.X, mea.Y);
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs pea)
{
Graphics grfx = pea.Graphics;
grfx.DrawBeziers(new Pen(ForeColor), apt);
Pen pen = new Pen(Color.FromArgb(0x80, ForeColor));
grfx.DrawLine(pen, apt[0], apt[1]);
grfx.DrawLine(pen, apt[2], apt[3]);
}
}
Программа фиксирует конечные точки кривой, но позволяет перемещать мышью управляющие точки. Точка p1 перемещается левой кнопкой, а p2 — правой. Функция «захвата» управляющих точек реализована здесь так: при нажатии левой или правой кнопки программа с помощью статического свойства Cursor.Position перемещает курсор к соответствующей управляющей точке. Программа также соединяет серыми линиями конечные точки с управляющими. Вот ее типичный вид:

Кривые Безье удобно использовать в программах художественной графики, так как они обладают рядом полезных свойств. Во-первых, после небольшой практики вы без труда сможете придать кривой желаемую форму.
Во-вторых, кривой Безье очень удобно управлять. Некоторые сплайны не проходят ни через одну из задающих их точек, кривая же Безье всегда закреплена двумя конечными точками (ниже мы увидим, что в этом состоит одна из предпосылок, на которых строится вывод формул Безье). Кроме того, у некоторых сплайнов есть особые точки, в которых кривая разворачивается в бесконечность (что редко бывает желательно в компьютерной графике). Кривая Безье ведет себя намного лучше. Фактически она никогда не выходит за пределы четырехугольника (называемого выпуклой оболочкой), образованного линиями, соединяющими конечные и управляющие точки (способ соединения конечных и управляющих точек при образовании этого четырехугольника зависит от формы конкретной кривой).
Третье свойство кривых Безье касается связи между конечными и управляющими точками. Если провести из конечной точки луч через первую управляющую точку, то он всегда будет проходить по касательной к кривой Безье в ее конечной точке и будет направлен в ту же сторону, что и кривая. Это последние предпосылки для вывода формул Безье.
В-четвертых, кривые Безье часто принимают эстетичные формы, на которые приятно смотреть. Понимаю, что этот критерий субъективен, но я не единственный, кто находит кривые Безье весьма изящными.
| netlib.narod.ru | < Назад | Оглавление | Далее > |