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 | < Назад | Оглавление | Далее > |