Список работ

C#, стандартная графика: системы итерируемых функций

Содержание

Введение

Система итерированных функций (СИФ) - это совокупность аффинных преобразований над точкой, которая после некоторого чиса итераций достигает аттрактора и будет затем перемещаться, не покидая его.
Отображение точки, находящейся на аттракторе, после каждого преобразования даст картинку фрактала (рис. 1).

СИФ-папоротник

Рис. 1. Папоротник из 10'000 точек (окружностей)

В работе приводятся алгоритм и программа на C# пострения 2d-СИФ. Тип проекта - Windows Form Application.

Алгоритм построения СИФ-фрактала

  1. Задать nm - число выводимых точек.
  2. Выполнить, начав с произвольной точки, nm аффинных преобразований, не выводя образа перемещаемой точки, и найти габаритный прямоугольник (minX, maxX, minY, maxY) выводимого фрактала. Текущее аффинное преобразование выбирается случайным образом из заданной СИФ.
  3. Выполнить, начав с последней точки предшествующего этапа, nm аффинных преобразований, выводя на каждой итерации образ перемещаемой точки, используя размеры габаритного прямоугольника для преобразования мировых координат в оконные.

Множество выведенных точек представит результирующий фрактал.

Реализация

Вывод точек, принадлежащих СИФ-фракталу, выполняется в графическаю область формы – объект System.Windows.Forms.PictureBox.
PictureBox можно вставить в форму, например, найдя PictureBox в списке Toolbox (поле Search Toolbox).
В проекте область графического вывода имеет имя pictureBoxIFS.
Для графического вывода создаются следующие объекты:

Точки отображаются в виде окружностей.
Визуализация образа выполняется в результате определения свойства Image объекта pictureBoxIFS:

pictureBoxIFS.Image = IFSImage;

Код построения СИФ-фрактала:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplicationIFS
{
 public partial class FormIFS : Form
 {
  // Образ для отображения СИФ
  public Image IFSImage;
  // Графический объект для образа IFSImage
  public Graphics IFSGraphics;
  // Текущий координаты образа (СИФ-фрактала)
  public double x, y;
  // Габариты образа в мировой системе координат
  public double minX, maxX, minY, maxY;
  // Число выводимых точек
  public int nm = 10000;
  // Число строк в СИФ
  public int nCol = 4;
  // Датчик случайных чисел
  public Random rand = new Random();
  //
  public FormIFS()
  {
   InitializeComponent();
   int w = pictureBoxIFS.Width, h = pictureBoxIFS.Height;
   IFSImage = new Bitmap(w, h);
   IFSGraphics = Graphics.FromImage(IFSImage);
   // Цвет фона
   IFSGraphics.FillRectangle(Brushes.Ivory, 0, 0, w, h); // Or IFSImage.Width, IFSImage.Height
   pictureBoxIFS.Image = IFSImage;
  }
  private int findK(double[] col)
  {
   // r - число из диапазона [0.0, 1.0], возвращаемое датчиком случайных чисел
   double p = 0.0, r = rand.NextDouble();
   int j;
   // Выбираем случайным образом очередное преобразование СИФ
   for (j = 0; j < nCol; j++)
   {
    p += col[j];
    if(r <= p) break;
   }
   return j;
  }
  // Аффинные преобразования координат
  private void affine(double[] ifs)
  {
   double x2 = x * ifs[0] + y * ifs[1] + ifs[4];
   y = x * ifs[2] + y * ifs[3] + ifs[5];
   x = x2;
  }
  // Копирование массива
  private void copyArray(int n, double[,] ifsA, int i, double[] ifsB)
  {
   for (int j = 0; j < n; j++) ifsB[j] = ifsA[i, j];
  }
  // Находит простым перебором minX, minY, maxX, maxY - соответственно
  // минимальные и максимальные мировые координаты точки изображения
  private void fconv(double[,] ifs1_4)
  {
   double[] ifs = {0, 0, 0, 0, 0, 0}, col = {0, 0, 0, 0};
   maxX = -1.0e10; minX = 1.0e10;
   maxY = -1.0e10; minY = 1.0e10;
   // Ищем начальную точку, используя первое уравнение СИФ
   copyArray(6, ifs1_4, 0, ifs);
   // Копируем вероятности выбора преобразования в массив col
   for (int i2 = 0; i2 < nCol; i2++) col[i2] = ifs1_4[i2, 6];
   // Полностью воспроизводим цикл генерации изображения
   for(int i = 0; i < nm; i++)
   {
    int k = findK(col);
    // Копируем текущее преобразование в массив ifs и затем вычисляем новые координаты точки
    copyArray(6, ifs1_4, k, ifs);
    affine(ifs);
    // Корректируем наши представления о максимальных и минимальных координатах образа
    maxX = Math.Max(x, maxX); minX = Math.Min(x, minX);
    maxY = Math.Max(y, maxY); minY = Math.Min(y, minY);
   }
  }
  // Вывод образа (выводится nm точек)
  private void render(double[,] ifs1_4)
  {
   int w = pictureBoxIFS.Width, h = pictureBoxIFS.Height;
   int d = 50;
   double[] ifs = { 0, 0, 0, 0, 0, 0 }, col = { 0, 0, 0, 0 };
   double wX = maxX - minX;
   double hY = maxY - minY;
   // Копируем вероятности выбора преобразования в массив col
   for (int i2 = 0; i2 < nCol; i2++) col[i2] = ifs1_4[i2, 6];
   // Цикл генерации изображения
   for (int i = 0; i < nm; i++)
   {
    int k = findK(col);
    // Копируем текущее преобразование в массив ifs и затем вычисляем новые координаты точки
    copyArray(6, ifs1_4, k, ifs);
    affine(ifs);
    // Преобразование мировых координат в координаты видового порта
    // Начало координат видового порта в нижнем левом углу окна вывода
    double xP = (x - minX) / wX;
    double yP = (y - minY) / hY;
    int iX = Convert.ToInt16(d / 2 + xP * (w - d));
    int iY = Convert.ToInt16(h - d / 2 - yP * (h - d));
    // For some case
    if (iX < 0 || iX > w || iY < 0 || iY > h) continue;
    // Используем координаты видового порта
    IFSGraphics.FillEllipse(Brushes.Orchid, iX, iY, 4, 4);
   }
   pictureBoxIFS.Image = IFSImage;
  }
  private void buttonGo_Click(object sender, EventArgs e)
  {
   // Массив, задающий СИФ
   // Curl
   //double[,] ifs1_4 = {{0.04, 0.22, 0.31, -0.03, 0.63, -1.74, 0.13},
   //     {-0.02, 0.00, -0.32, 0.26, -0.17, -1.35, 0.01},
   //     {0.79, 0.06, -0.03, 0.73, -0.02, 1.03, 0.74},
   //     {-0.03, -0.30, 0.35, -0.04, -0.68, -0.94, 0.12}};
   // Fern
   double[,] ifs1_4 = {{0.0, 0.0, 0.0, 0.16, 0.0, 0.0, 0.01},
        {0.85, 0.04, -0.04, 0.85, 0.0,1.6, 0.85},
        {0.2, -0.26, 0.23, 0.22, 0.0, 1.6, 0.07},
        {-0.15, 0.28, 0.26, 0.24, 0.0, 0.44, 0.07}};
   fconv(ifs1_4);
   render(ifs1_4);
  }
 }
}

Заключение

Больше иформации о фракталах можно получить, например, на 100byte.ru/stdntswrks/fr/fr.html.

Список работ

Рейтинг@Mail.ru