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. Эллипс также центрирован относительно начала координат. Чтобы переместить центр эллипса в точку с координатами (CXCY), формулы должны принять такой вид:


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);
      }
  }

Поскольку центр эллипса находится на пересечении прямых, делящих экран надвое по ширине и высоте, а ширина и высота эллипса равны ширине и высоте области экрана, я смог несколько упростить формулы. Я аппроксимировал число точек массива как число точек, достаточное для изображения прямоугольника, периметр которого равен периметру экрана.


Рис. 5.5.

Далее вы увидите, что в классе 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);
      }
  }

А вот как выглядит эта фигура:


Рис. 5.6.


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

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