Задача : создание приложения, реализующего основные алгоритмы растеризации линии и окружности Представленное приложение реализует некоторые растровые алгоритмы. Среди них алгоритмы Брезенхема и Ву. Также для сравнения представлены аналогичные графические примитивы, встроенные в платформу .NET. В программе ведется работа с двумя классами : класс Form1, наследующий класс Form и выводящий изображения на форму, и статический класс RasterAlgorithms, содержащий реализации алгоритмов в статических методах. Далее описаны реализованные алгоритмы. 1. Алгоритм Брезенхема для 4-связной линии. //file Form1.cs using System; using System.Drawing; using System.Windows.Forms; namespace RasterAlgorithms { public partial class Form1 : Form { //Метод Main() - точка входа в программу public static void Main() { using (Form1 frm = new Form1()) { Application.Run(frm); } } //Конструктор пользовательского класса, наследующего класс Form public Form1() { InitializeComponent(); ResizeRedraw = true; } //Обработчик события OnPaint. Отрисовывает на форме её содержимое protected override void OnPaint(PaintEventArgs e) { //Устранение ошибки смещения на 1 пиксел e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; //Отрисовка 4-связной линии, построенной по алгоритму Брезенхема RasterAlgorithms.Bresenham4Line( e.Graphics, Color.Black, 50, 34, ClientSize.Width - 10, ClientSize.Height - 50); //Отрисовка 8-связной линии, построенной по алгоритму Брезенхема RasterAlgorithms.Bresenham8Line( e.Graphics, Color.Black, 30, 34, ClientSize.Width - 10, ClientSize.Height - 30); //Отрисовка линии, построенной по алгоритму Ву RasterAlgorithms.DrawWuLine( e.Graphics, Color.Black, 10, 34, ClientSize.Width - 10, ClientSize.Height - 10); //Обычная линия e.Graphics.DrawLine(new Pen(Color.Black), 10, 54, ClientSize.Width - 30, ClientSize.Height - 10); //Настройки сглаживания e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; //Линия с установленными параметрами сглаживания e.Graphics.DrawLine(new Pen(Color.Black), 10, 74, ClientSize.Width - 50, ClientSize.Height - 10); //Отрисовка окружности, построенной по алгоритму Брезенхема RasterAlgorithms.BresenhamCircle( e.Graphics, Color.Black, 400, 150, 75); //Отрисовка окружности, построенной по модифицированному алгоритму Ву RasterAlgorithms.DrawWuCircle( e.Graphics, Color.Black, 600, 150, 75); //Окружность e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; e.Graphics.DrawEllipse(new Pen(Color.Black), 100, 350, 150, 150); //Окружность с установленными параметрами сглаживания e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; e.Graphics.DrawEllipse(new Pen(Color.Black), 300, 350, 150, 150); } //Описание элементов меню private void toolStripMenuItem2_Click(object sender, EventArgs e) { Application.Exit(); } private void toolStripMenuItem4_Click(object sender, EventArgs e) { MessageBox.Show( "Линии (сверху вниз) : \n" + "1. 4-связная линия, построенная по алгоритму Брезенхема\n" + "2. 8-связная линия, построенная по алгоритму Брезенхема\n" + "3. Линия, построенная по алгоритму Ву\n" + "4. Линия, встроенная в платформу\n" + "5. Линия с эффектом сглаживания, встроенная в платформу\n\n" + "Окружности (слева направо сверху вниз) : \n" + "1. Окружность, построенная по алгоритму Брезенхема\n" + "2. Окружность, построенная по алгоритму Ву\n" + "3. Окружность, встроенная в платформу\n" + "4. Окружность с эффектом сглаживания, встроенная в платформу\n", "Help"); } } //Статический класс, содержащий реализацию растровых алгоритмов static class RasterAlgorithms { //Статический метод, реализующий отрисовку линии по алгоритму Ву public static void DrawWuLine(Graphics g, Color clr, int x0, int y0, int x1, int y1) { //Вычисление изменения координат int dx = (x1 > x0) ? (x1 - x0) : (x0 - x1); int dy = (y1 > y0) ? (y1 - y0) : (y0 - y1); //Если линия параллельна одной из осей, рисуем обычную линию - заполняем все пикселы в ряд if (dx == 0 || dy == 0) { g.DrawLine(new Pen(clr), x0, y0, x1, y1); return; } //Для Х-линии (коэффициент наклона < 1) if (dy < dx) { //Первая точка должна иметь меньшую координату Х if (x1 < x0) { x1 += x0; x0 = x1 - x0; x1 -= x0; y1 += y0; y0 = y1 - y0; y1 -= y0; } //Относительное изменение координаты Y float grad = (float)dy / dx; //Промежуточная переменная для Y float intery = y0 + grad; //Первая точка PutPixel(g, clr, x0, y0, 255); for (int x = x0 + 1; x < x1; x++) { //Верхняя точка PutPixel(g, clr, x, IPart(intery), (int)(255 - FPart(intery) * 255)); //Нижняя точка PutPixel(g, clr, x, IPart(intery) + 1, (int)(FPart(intery) * 255)); //Изменение координаты Y intery += grad; } //Последняя точка PutPixel(g, clr, x1, y1, 255); } //Для Y-линии (коэффициент наклона > 1) else { //Первая точка должна иметь меньшую координату Y if (y1 < y0) { x1 += x0; x0 = x1 - x0; x1 -= x0; y1 += y0; y0 = y1 - y0; y1 -= y0; } //Относительное изменение координаты X float grad = (float)dx / dy; //Промежуточная переменная для X float interx = x0 + grad; //Первая точка PutPixel(g, clr, x0, y0, 255); for (int y = y0 + 1; y < y1; y++) { //Верхняя точка PutPixel(g, clr, IPart(interx), y, 255 - (int)(FPart(interx) * 255)); //Нижняя точка PutPixel(g, clr, IPart(interx) + 1, y, (int)(FPart(interx) * 255)); //Изменение координаты X interx += grad; } //Последняя точка PutPixel(g, clr, x1, y1, 255); } } //Статический метод, реализующий отрисовку окружности по алгоритму Ву public static void DrawWuCircle(Graphics g, Color clr, int _x, int _y, int radius) { //Установка пикселов, лежащих на осях системы координат с началом в центре PutPixel(g, clr, _x + radius, _y, 255); PutPixel(g, clr, _x, _y + radius, 255); PutPixel(g, clr, _x - radius + 1, _y, 255); PutPixel(g, clr, _x, _y - radius + 1, 255); float iy = 0; for (int x = 0; x <= radius * Math.Cos(Math.PI / 4); x++) { //Вычисление точного значения координаты Y iy = (float)Math.Sqrt(radius * radius - x * x); //IV квадрант, Y PutPixel(g, clr, _x - x, _y + IPart(iy), 255 - (int)(FPart(iy) * 255)); PutPixel(g, clr, _x - x, _y + IPart(iy) + 1, (int)(FPart(iy) * 255)); //I квадрант, Y PutPixel(g, clr, _x + x, _y + IPart(iy), 255 - (int)(FPart(iy) * 255)); PutPixel(g, clr, _x + x, _y + IPart(iy) + 1, (int)(FPart(iy) * 255)); //I квадрант, X PutPixel(g, clr, _x + IPart(iy), _y + x, 255 - (int)(FPart(iy) * 255)); PutPixel(g, clr, _x + IPart(iy) + 1, _y + x, (int)(FPart(iy) * 255)); //II квадрант, X PutPixel(g, clr, _x + IPart(iy), _y - x, 255 - (int)(FPart(iy) * 255)); PutPixel(g, clr, _x + IPart(iy) + 1, _y - x, (int)(FPart(iy) * 255)); //С помощью инкремента устраняется ошибка смещения на 1 пиксел x++; //II квадрант, Y PutPixel(g, clr, _x + x, _y - IPart(iy), (int)(FPart(iy) * 255)); PutPixel(g, clr, _x + x, _y - IPart(iy) + 1, 255 - (int)(FPart(iy) * 255)); //III квадрант, Y PutPixel(g, clr, _x - x, _y - IPart(iy), (int)(FPart(iy) * 255)); PutPixel(g, clr, _x - x, _y - IPart(iy) + 1, 255 - (int)(FPart(iy) * 255)); //III квадрант, X PutPixel(g, clr, _x - IPart(iy), _y - x, (int)(FPart(iy) * 255)); PutPixel(g, clr, _x - IPart(iy) + 1, _y - x, 255 - (int)(FPart(iy) * 255)); //IV квадрант, X PutPixel(g, clr, _x - IPart(iy), _y + x, (int)(FPart(iy) * 255)); PutPixel(g, clr, _x - IPart(iy) + 1, _y + x, 255 - (int)(FPart(iy) * 255)); //Возврат значения x--; } } //Статический метод, реализующий отрисовку 8-связной линии по алгоритму Брезенхема static public void Bresenham8Line(Graphics g, Color clr, int x0, int y0, int x1, int y1) { //Изменения координат int dx = (x1 > x0) ? (x1 - x0) : (x0 - x1); int dy = (y1 > y0) ? (y1 - y0) : (y0 - y1); //Направление приращения int sx = (x1 >= x0) ? (1) : (-1); int sy = (y1 >= y0) ? (1) : (-1); if (dy < dx) { int d = (dy << 1) - dx; int d1 = dy << 1; int d2 = (dy - dx) << 1; PutPixel(g, clr, x0, y0, 255); int x = x0 + sx; int y = y0; for (int i = 1; i <= dx; i++) { if (d > 0) { d += d2; y += sy; } else d += d1; PutPixel(g, clr, x, y, 255); x++; } } else { int d = (dx << 1) - dy; int d1 = dx << 1; int d2 = (dx - dy) << 1; PutPixel(g, clr, x0, y0, 255); int x = x0; int y = y0 + sy; for (int i = 1; i <= dy; i++) { if (d > 0) { d += d2; x += sx; } else d += d1; PutPixel(g, clr, x, y, 255); y++; } } } //Статический метод, реализующий отрисовку 4-связной линии по алгоритму Брезенхема public static void Bresenham4Line(Graphics g, Color clr, int x0, int y0, int x1, int y1) { int dx = x1 - x0; int dy = y1 - y0; int d = 0; int d1 = dy << 1; int d2 = -(dx << 1); PutPixel(g, clr, x0, y0, 255); int x = x0; int y = y0; for (int i = 1; i <= dx + dy; i++) { if (d > 0) { d += d2; y++; } else { d += d1; x++; } PutPixel(g, clr, x, y, 255); } } //Статический метод, реализующий отрисовку окружности по алгоритму Брезенхема public static void BresenhamCircle(Graphics g, Color clr, int _x, int _y, int radius) { int x = 0, y = radius, gap = 0, delta = (2 - 2 * radius); while (y >= 0) { PutPixel(g, clr, _x + x, _y + y, 255); PutPixel(g, clr, _x + x, _y - y, 255); PutPixel(g, clr, _x - x, _y - y, 255); PutPixel(g, clr, _x - x, _y + y, 255); gap = 2 * (delta + y) - 1; if (delta < 0 && gap <= 0) { x++; delta += 2 * x + 1; continue; } if (delta > 0 && gap > 0) { y--; delta -= 2 * y + 1; continue; } x++; delta += 2 * (x - y); y--; } } //Метод, устанавливающий пиксел на форме с заданными цветом и прозрачностью private static void PutPixel(Graphics g, Color col, int x, int y, int alpha) { g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, col)), x, y, 1, 1); } //Целая часть числа private static int IPart(float x) { return (int)x; } //дробная часть числа private static float FPart(float x) { while (x >= 0) x--; x++; return x; } } } //file Form1.Designer.cs namespace RasterAlgorithms { partial class Form1 { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip1.SuspendLayout(); this.SuspendLayout(); // // menuStrip1 // this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripMenuItem1, this.toolStripMenuItem3}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; this.menuStrip1.Size = new System.Drawing.Size(784, 24); this.menuStrip1.TabIndex = 1; this.menuStrip1.Text = "menuStrip1"; // // toolStripMenuItem1 // this.toolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripMenuItem2}); this.toolStripMenuItem1.Name = "toolStripMenuItem1"; this.toolStripMenuItem1.Size = new System.Drawing.Size(37, 20); this.toolStripMenuItem1.Text = "File"; // // toolStripMenuItem2 // this.toolStripMenuItem2.Name = "toolStripMenuItem2"; this.toolStripMenuItem2.Size = new System.Drawing.Size(152, 22); this.toolStripMenuItem2.Text = "Exit"; this.toolStripMenuItem2.Click += new System.EventHandler(this.toolStripMenuItem2_Click); // // toolStripMenuItem3 // this.toolStripMenuItem3.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripMenuItem4}); this.toolStripMenuItem3.Name = "toolStripMenuItem3"; this.toolStripMenuItem3.Size = new System.Drawing.Size(44, 20); this.toolStripMenuItem3.Text = "Help"; // // toolStripMenuItem4 // this.toolStripMenuItem4.Name = "toolStripMenuItem4"; this.toolStripMenuItem4.Size = new System.Drawing.Size(152, 22); this.toolStripMenuItem4.Text = "Help"; this.toolStripMenuItem4.Click += new System.EventHandler(this.toolStripMenuItem4_Click); // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(784, 562); this.Controls.Add(this.menuStrip1); this.MainMenuStrip = this.menuStrip1; this.Name = "Form1"; this.Text = "Form1"; this.menuStrip1.ResumeLayout(false); this.menuStrip1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem3; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem4; } }
Ключевые слова:
алгоритм растр брезенхем сглаживание
|
|||||||