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

Знакомство с кривыми Безье на практике

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


Рис. 13.1.

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


Рис. 13.2.

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


Рис. 13.3.

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


Рис. 13.4.

Чтобы нарисовать кривую Безье в программе 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 перемещает курсор к соответствующей управляющей точке. Программа также соединяет серыми линиями конечные точки с управляющими. Вот ее типичный вид:


Рис. 13.5.

Кривые Безье удобно использовать в программах художественной графики, так как они обладают рядом полезных свойств. Во-первых, после небольшой практики вы без труда сможете придать кривой желаемую форму.

Во-вторых, кривой Безье очень удобно управлять. Некоторые сплайны не проходят ни через одну из задающих их точек, кривая же Безье всегда закреплена двумя конечными точками (ниже мы увидим, что в этом состоит одна из предпосылок, на которых строится вывод формул Безье). Кроме того, у некоторых сплайнов есть особые точки, в которых кривая разворачивается в бесконечность (что редко бывает желательно в компьютерной графике). Кривая Безье ведет себя намного лучше. Фактически она никогда не выходит за пределы четырехугольника (называемого выпуклой оболочкой), образованного линиями, соединяющими конечные и управляющие точки (способ соединения конечных и управляющих точек при образовании этого четырехугольника зависит от формы конкретной кривой).

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

В-четвертых, кривые Безье часто принимают эстетичные формы, на которые приятно смотреть. Понимаю, что этот критерий субъективен, но я не единственный, кто находит кривые Безье весьма изящными.


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

Сайт управляется системой uCoz