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

Визуализация контура

Чаще всего контур визуализируют при помощи одного из методов класса Graphics:


Методы Graphics (выборочно)



void DrawPath(Pen pen, GraphicsPath path)
void FillPath(Brush brush, GraphicsPath path)


Метод DrawPath рисует заданным пером прямые и кривые, составляющие контур. FillPath заливает внутренние области всех замкнутых фигур, используя заданную кисть. Хотя этот метод закрывает открытые фигуры, чтобы выполнить заливку, он не вносит в контур постоянных изменений. Если в контуре есть пересекающиеся линии, то заливка внутренних областей определяется значением свойства FillPath объекта GraphicsPath. При визуализации все точки контура подвергаются любым преобразованиям, установленным для объекта Graphics.

А теперь посмотрим, как все это работает на практике. Программа Flower рисует цветок при помощи контуров и преобразования.

Flower.cs

  //---------------------------------------
  // Flower.cs (C) 2001 by Charles Petzold
  //---------------------------------------
  using System;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Windows.Forms;

  class Flower: PrintableForm
  {
      public new static void Main()
      {
          Application.Run(new Flower());
      }
      public Flower()
      {
          Text = "Flower";
      }
      protected override void DoPage(Graphics grfx, Color clr, int cx, int cy)
      {
          // Рисуем зеленый стебель из нижнего левого угла к центру

          grfx.DrawBezier(new Pen(Color.Green, 10), 
                    new Point(0, cy),          new Point(0, 3 * cy / 4),
                    new Point(cx / 4, cy / 4), new Point(cx / 2, cy / 2));

          // Устанавливаем преобразование для оставшегося цветка

          float fScale = Math.Min(cx, cy) / 2000f;
          grfx.TranslateTransform(cx / 2, cy / 2);
          grfx.ScaleTransform(fScale, fScale);

          // Рисуем красные лепестки

          GraphicsPath path = new GraphicsPath();

          path.AddBezier(new Point(  0,    0), new Point(125,  125),
                         new Point(475,  125), new Point(600,    0));
          path.AddBezier(new Point(600,    0), new Point(475, -125), 
                         new Point(125, -125), new Point(  0,    0));

          for (int i = 0; i < 8; i++)
          {
              grfx.FillPath(Brushes.Red, path);
              grfx.DrawPath(Pens.Black, path);
              grfx.RotateTransform(360 / 8);
          }

          // Рисуем желтый круг в центре

          Rectangle rect = new Rectangle(-150, -150, 300, 300);
          grfx.FillEllipse(Brushes.Yellow, rect);
          grfx.DrawEllipse(Pens.Black, rect);
      }
  }

Исполнение метода DoPage начинается с рисования изображающей стебель цветка кривой Безье, которая начинается из левого нижнего угла и заканчивается в центре клиентской области (или страницы принтера). Далее программа задает глобальное преобразование, чтобы создать изотропную область для рисования, разбитую на четыре квадранта. Координаты этой области меняются от –1000 до 1000, а начало координат расположено в центре области.

Далее программа должна нарисовать несколько лепестков, и здесь в дело вступает контур. Если бы лепестки были эллиптическими, я просто вызвал бы метод FillEllipse. Но форма лепестка точнее определяется парой кривых Безье, а для заливки полученной фигуры нужен контур. Создав контур, программа восемь раз вызывает методы FillPath и DrawPath. Каждый раз после их вызова RotateTransform изменяет глобальное преобразование объекта Graphics, в результате лепестки располагаются по кругу вокруг центра цветка. Метод DoPage завершается рисованием желтого круга в центре клиентской области.


Рис. 15.5.

Уверен, вы помните программу Scribble из главы 8. Тогда я показывал, как сохранить все нарисованные пользователем линии при помощи класса ArrayList. Этот объект напоминает массив, способный динамически изменять свой размер. На самом деле применение объекта ArrayList весьма напоминает сохранение координат в контуре. Замена ArrayList объектом GraphicsPath позволяет существенно упростить программу, которая в этом случае становится даже проще, чем версия из главы 11 (ScribbleWithBitmap), сохраняющая рисунок при помощи скрытого изображения.

ScribbleWithPath.cs

  //-------------------------------------------------
  // ScribbleWithPath.cs (C) 2001 by Charles Petzold
  //-------------------------------------------------
  using System;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Windows.Forms;

  class ScribbleWithPath: Form
  {
      GraphicsPath path;
      bool         bTracking;
      Point        ptLast;

      public static void Main()
      {
          Application.Run(new ScribbleWithPath());
      }
      public ScribbleWithPath()
      {
          Text = "Scribble with Path";
          BackColor = SystemColors.Window;
          ForeColor = SystemColors.WindowText;

          // Создаем контур

          path = new GraphicsPath();
      }
      protected override void OnMouseDown(MouseEventArgs mea)
      {
          if (mea.Button != MouseButtons.Left)
              return;

          ptLast = new Point(mea.X, mea.Y);
          bTracking = true;

          // Начало фигуры

          path.StartFigure();
      }
      protected override void OnMouseMove(MouseEventArgs mea)
      {
          if (!bTracking)
              return;

          Point ptNew = new Point(mea.X, mea.Y);

          Graphics grfx = CreateGraphics();
          grfx.DrawLine(new Pen(ForeColor), ptLast, ptNew);
          grfx.Dispose();

          // Добавляем линию

          path.AddLine(ptLast, ptNew);

          ptLast = ptNew;
      }
      protected override void OnMouseUp(MouseEventArgs mea)
      {
          bTracking = false;
      }
      protected override void OnPaint(PaintEventArgs pea)
      {
          // Рисуем контур

          pea.Graphics.DrawPath(new Pen(ForeColor), path);
      }
  }

Помимо дополнительной инструкции using, для превращения версии программы Scribble, не сохраняющей пользовательские рисунки, в ScribbleWithPath, нужно определить контур как переменную-поле и добавить всего 4 инструкции, прокомментированные в тексте программы.

Контур создается в конструкторе формы. Когда курсор находится над клиентской областью формы, нажатие любой кнопки мыши вызывает метод StartFigure, начинающий новую фигуру. Вызов AddLine во время исполнения метода OnMouseMove добавляет к контуру новую линию, а метод OnPaint просто вызывает DrawPath.


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

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