скачать Лабораторная работа №2 Графические возможности Visual C#. Построение графика функции. Цель работы: Изучить основные возможности среды разработки для создания графических объектов. Познакомиться с базовым набором графических примитивов. 1. Теоретические сведения1.1. ОСОБЕННОСТИ GDI+Для рисования объектов в Windows Forms приложениях язык С# содержит очень богатый набор методов. Пространство имен Drawing содержит множество объектов, которые облегчают программисту работу с графикой. Специально для .NET платформы разработчики Microsoft разработали GDI+ библиотеку, значительно повысив возможности GDI (Graphic Device Interface). GDI+ включает возможности рисования простейших объектов (линии, эллипсы...), рисование различных объектов 2D графики, отображение файлов различных графических форматов (bmp, jpeg, gif, wmf, ico, tiff...) и многое другое. Перед началом рисования линий и фигур, вывода текста или отображения изображений с помощью библиотеки GDI+, необходимо создать графический объект. Графический объект представляет собой пространство для рисования и является объектом, используемым для создания изображения. Для работы с графикой необходимо выполнить два действия:
Графический объект может быть создан различными способами:
^ 1.2.1 Пространства имен и классы Весь графический инструментарий расположен в пространствах имен, перечисленных в табл. 2.1, Таблица 2.1. Пространства имен для отрисовки изображений
1.2.2 Класс Graphics В CTS для отрисовки компонентов предлагаются классы Pen, Brush, Font, Region, Bitmap, Palette и Graphics. Каждый из них может работать только в рамках заданного контекста графического устройства. Графическими устройствами являются дисплей, принтер, плоттер и т. п. Контекст графического устройства (далее — просто контекст устройства) представляет собой набор параметров, характеризующих это устройство и использующихся для вывода изображений, текста, линий и других графических объектов. Класс Graphics определяет набор свойств и методов для отрисовки различных изображений на поверхности контекста устройства. Он передается как параметр вызова обработчикам события Paint, и в этом случае его не нужно создавать или уничтожать. Для самостоятельного создания объекта Graphics могут использоваться его методы FromXXX (см. далее). В табл. 2.2 и 2.3 представлены наиболее важные свойства и методы класса. Таблица 2.2. Свойства класса Graphics
Таблица 2.3. Методы класса Graphics
Класс Graphics является базовым классом для отрисовки изображений. 1.2.3 Отрисовка линий Для отрисовки линий CTS предоставляет два класса — Реn и Brush, а также метод DrawLine класса Graphics. Класс Реn позволяет выбирать толщину линий, добавлять к ним наконечники, а также нужным образом соединять линии. Класс Brush обеспечивает раскраску линии, в том числе заполнение ее градиентным цветом, узором или текстурой. Метод DrawLine осуществляет собственно отрисовку линии, используя нужные перо Реn и кисть Brush. Методами BeginContainer () и EndContainer () создается и уничтожается графический контейнер — специальный объект класса GraphicsContainer (пространство имен System.Drawing.Drawing2D), в котором сохраняются текущие параметры объекта Graphics. При вызове BeginContainer () параметры помещаются в стек. Любые изменения параметров до вызова EndContainer () уничтожаются и восстанавливаются сохраненные в стеке. Контейнеры могут быть вложенными, но каждый вызов EndContainer () уничтожает самый последний контейнер (количество вызовов EndContainer () может быть меньше вызовов BeginContainer () ). В следующем примере создается контейнер, затем начало координат смещается на 100 пикселов влево и вниз, вычерчивается черной утолщенной линией прямоугольник и контейнер уничтожается. После этого вычерчивается синий прямоугольник того же размера (рис. 2.1). В листинге 2.1 представлен обработчик события Form. Paint описанного примера. ![]() Рис. 2.1. Демонстрация работы с контейнером Листинг 2.1. Демонстрация работы с контейнером using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace ContainerDemo { public partial class Forml : Form { public Forml() { InitializeComponent(); } private void Forml_Paint(object sender, PaintEventArgs e) { // Создаем контейнер: GraphicsContainer GS = e.Graphics.BeginContainer(); // Смещаем начало координат: e.Graphics.TranslateTransform(100, 100); // Вычерчиваем черный прямоугольник: Pen P = new Pen(Color.Black, 2); e.Graphics.DrawRectangle(P, 0, 0, 200, 200); e.Graphics.EndContainer(GS); // Удаляем контейнер // Заливаем синий прямоугольник: SolidBrush В = new SolidBrush(Color.Blue); e.Graphics.FillRectangle(В, 0, 0, 200, 200); } } } Аналогично работают методы Save () и Restore (). В методах DrawArc () и DrawPie () используются ограничивающие углы Start и Finish. Начало отсчета углов соответствует радиальной горизонтальной линии, направленной вправо. Положительные углы отсчитываются по часовой стрелки, отрицательные — против. Методы SetClip () , IntersectClip () и ResetClip () управляют размерами и положением области отрисовки. Класс Graphics обеспечивает возможность использования графических объектов класса GraphicsPath (пространство имен System.Drawing.Drawing2D). Эти объекты имеют методы, позволяющие наполнять их графическими примитивами, линиями и кривыми. Метод DrawPath () вычерчивает все содержимое объекта GraphicsPath разом. Рисунок 2.4 получен с помощью показанного в листинге 2.3 обработчика события Paint . ![]() Рис. 2.4. Демонстрация метода DrawPath Листинг 2.3. Демонстрация метода DrawPath using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace GraphicPath { public partial class Forml : Form { public Forml() { InitializeComponent() ; } private void Forml_Paint(object sender, PaintEventArgs e) { // Создаем объект GraphicsPath: GraphicsPath GP = new GraphicsPath(); // Наполняем его эллипсами: GP.AddEllipse(60, 0, 60, 40); GP.AddEllipse(60, 40, 60, 80); GP.AddEllipse(31, 60, 30, 30); GP.AddEllipse(119, 60, 30, 30); GP.AddEllipse(55, 120, 30, 20); GP.AddEllipse(95, 120, 30, 20); e.Graphics.TranslateTransform(60, 60); // Отрисовываем все содержимое объекта GpahicsPath: Pen P = new Pen(Color.Black, 3); e.Graphics.DrawPath(P, GP) ; } } } Методы DrawBezier() и DrawCurve() рисуют кривые линии. Кривая Безье определяется начальной и конечной, а также несколькими промежуточными точками (в методе DrawBezier() две промежуточные точки). В методе DrawCurve () используется сплайн-интерполяция между произвольным количеством точек. На рис. 2.5 показаны примеры кривых, создаваемых этими методами. Листинг 2.4. Демонстрация вычерчивания кривых линий private void Forml_Paint(object sender, PaintEventArgs e) { // Точки излома для метода Curve: Point [] Curve = new Point [7]; Curve[0] = new Point (50, 50); Curve[1] = new Point(100, 25); Curve[2] = new Point(200, 50); Curve[3] = new Point (100, 150); Curve[4] = new Point(300, 100); Curve[5] = new Point (350, 200); Curve[6] = new Point(250, 150); // Рисуем кривую: Pen P = new Pen(Color.Black, 2); e.Graphics.DrawCurve(P, Curve); // Рисуем ломаную линию по координатам кривой: Реп р = new Pen(Color.Blue, 1); е.Graphics.DrawLines(p, Curve); // Точки излома для метода Bezier: Point[] Bezier = new Point[4]; Bezier[0] = new Point(500, 50); Bezier [1] = new Point(350, 100); Bezier[2] = new Point(650, 150); Bezier[3] = new Point(500, 200); // Рисуем кривую Безье: e.Graphics.DrawBezier(P, Bezier[0], Bezier[l], Bezier [2], Bezier[3]); // Рисуем ломаную линию по координатам кривой Безье: е.Graphics.DrawLines(p, Bezier); } ![]() Рис. 2.5. Демонстрация методов DrawLines, DrawCurve и DrawBezier Этот рисунок создан обработчиком из листинга 2.4 . Метод MeasureCharacterRanges () возвращает объекты типа Region, положение и размеры которых соответствуют положению и размерам некоторых подстрок в заданной строке. Параметр обращения SF класса StringFormat имеет метод SetMeasurableCharacterRanges (), с его помощью задаются порядковый номер символа (нумерация начинается с нуля) и количество символов, положение которых нужно определить. ПРИМЕЧАНИЕ Описываемые методы правильно работают только со строками, созданными шрифтами типа Courier, в которых ширина знакоместа не изменяется (такие шрифты называются моноширинными). В листинге 2.5 представлен обработчик события Paint формы, создающий окно, показанное на рис. 2.6. ![]() Рис. 2.6. Демонстрация метода MeasureCharacterRanges Листинг 2.5. Демонстрация метода MeasureCharacterRanges private void Forml_Paint(object sender, PaintEventArgs e) { // Создаем моноширинный шрифт: Font F = new Font("Courier New", 22, FontStyle.Bold); // Выводим строку: string S = "First and Second ranges"; SolidBrush В = new SolidBrush(Color.Black); e.Graphics.Drawstring(S, F, B, 50.OF, 50.OF); // Определяем прямоугольник строки: float w = e.Graphics.MeasureString(S, F).Width; // Ширина float h = e.Graphics.MeasureString (S, F).Height; // Высота // Прямоугольник строки: RectangleF Layout = new RectangleF(50.Of, 50.Of, w, h); // Готовим измерение: StringFormat SF = new StringFormat(); SF.FormatFlags = StringFormatFlags.DirectionRightToLeft; CharacterRange[] CR = new CharacterRange[2]; CR[0] = new CharacterRange(0, 5); // Параметры 1-й подстроки CR[1] = new CharacterRange(10, 6); // Параметры 2-й подстроки // Измеряем: SF.SetMeasurableCharacterRanges(CR); // Обрабатываем результат: Region[] Reg = new Region[2]; // Области для подстрок Reg = e.Graphics.MeasureCharacterRanges(S, F, Layout, SF) ; RectangleF MR = Reg[0].GetBounds(e.Graphics); // 1-я подстрока Pen P = new Pen(Color.Red); е.Graphics.DrawRectangle (P, Rectangle.Round(MR)); // Очерчиваем MR = Reg[1].GetBounds(e.Graphics); // 2-я подстрока e.Graphics.DrawRectangle(P, Rectangle.Round(MR)); // Очерчиваем } Вызовом Rectangle .Round (MR) прямоугольник с вещественными координатами преобразуется в прямоугольник с целочисленными координатами. ПРИМЕЧАНИЕ Вещественные константы в С# принадлежат типу double. Для приведения их к типу float можно ставить символ F или f за последней цифрой константы. Свойство Transform содержит объект класса Matrix (пространство имен System . Drawing. Drawing2D). Этот объект определяет матрицу 3x3 для так называемых аффинных преобразований координат. При аффинных преобразованиях поворот и масштабирование изображений осуществляются путем нужного изменения системы координат. Для этого в состав класса включены методы Translate () (смещение начала координат), Scale () (масштабирование) и RotateAt () (поворот на заданный угол). ![]() Рис. 2.7. Смещение начала координат В листинге 2.6 демонстрируется метод Translate: сначала создается квадрат со стороной 100 пикселов и выводится синим цветом в левом верхнем углу экрана; затем начало координат смещается на 100 пикселов вниз и вправо, после чего квадрат вычерчивается вновь красным цветом. В результате в окне формы оказываются два квадрата: синий в левом верхнем углу и смещенный на 100 пикселов вправо и вниз красный (рис. 2.7). Листинг 2.6. Демонстрация метода Transform using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace TransformDemo { public partial class Forml : Form { public Forml() { InitializeComponent() ; } private void Form1_Paint(object sender, PaintEventArgs e) { // Создаем квадрат: Rectangle R = new Rectangle (0, 0, 100, 100); // Выводим его: Pen P = new Pen(Color.Blue, 2); e.Graphics.DrawRectangle(P, R); // Создаем матрицу: Matrix M = new Matrix(); // Смещаем начало координат: M.Translate (100, 100); // Вставляем в контекст устройства: е.Graphics.Transform = М; // Вновь выводим квадрат: P.Color = Color.Red; е.Graphics.DrawRectangle(P, R); } } } Для демонстрации метода Scale () поместите на форму два компонента Track-Bar (для этого в окне Toolbox раскройте узел All Windows Forms) и назовите их tbHor и tbVer. В свойство Orientation компонента tbVer поместите значение Vertical и разместите компоненты на форме примерно так, как показано на рис. 2.8 . ![]() Рис. 2.8. Масштабирование изображения В свойства Maximum, Minimum, TickFrequency и Value компонентов поместите значения 100, 1, 10, 10 соответственно. Создайте для их события Value- Change и для события Paint формы обработчики (для события tbVer_Value-Change назначьте обработчик события tbHor_ValueChange), показанные в листинге 2.7. Листинг 2.7. Масштабирование изображений using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace ScaleDemo { public partial class Forml : Form { public Forml() { InitializeComponent (); } private void tbHor_ValueChanged(object sender, EventArgs e) // При изменении значения свойства Value отрисовываем форму заново { Refresh (); } private void Forml_Paint(object sender, PaintEventArgs e) { // Создаем матрицу: Matrix M = new Matrix(); // Масштабируем с учетом положения ползунков TrackBar: М.Scale(tbHor.Value / 10, tbVer.Value /10); // Вставляем матрицу в контекст устройства: е.Graphics.Transform = М; // Вычерчиваем прямоугольник: Реп Р = new Pen (Color.Blue, 2); е.Graphics.DrawRectangle(P, 70, 70, 200, 200) ; } } } При масштабировании в матрицу помещаются два коэффициента (dX и dY), на которые будут умножаться значения, соответственно, горизонтальной и вертикальной осей. Если коэффициент меньше 1, изображение сжимается, если больше — растягивается. Так как значения свойства Value компонента TrackBar не могут быть меньше единицы, эти значения при формировании матрицы делятся на 10. Метод RotateAt () класса Matrix создает матрицу, поворачивающую оси координат на заданный угол относительно указанной точки. На рис. 2.9 показана форма с надписями, повернутыми на разные углы относительно горизонтального направления. ![]() Рис. 2.9. Поворот изображения Эту форму создала программа, представленная в листинге 2.8. Листинг 2.8. Поворот изображений using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace RotateDemo { public partial class Forml : Form { public Forml() { InitializeComponent(); } private void Forml_Paint(object sender, PaintEventArgs e) { // Строка для вывода: string S = " Visual C# v.2.0"; // Создаем графический путь: GraphicsPath GP = new GraphicsPath(); // Создаем семейство шрифтов: FontFamily FF = new FontFamily("Courier"); // Точка вывода - середина формы: Point Р = new Point(Width / 2, Height 12); // Помещаем строку в ГП: StringFormat SF = new StringFormat(StringFormat.GenericDefault); GP.AddString(S, FF, (int)FontStyle.Bold, 20, P, SF) ; // Создаем матрицу поворота: Matrix M = new Matrix(); // Цикл вывода: Pen p = new Pen(Color.Black, 1); for (int k = 1; k < 9; k++) { // Выводим надпись с текущим поворотом осей: е.Graphics.DrawPath(p, GP); // Поворачиваем оси для следующего прохода: M.RotateAt(45, Р); }} При добавлении в графический путь строки помимо собственно строки нужно задать семейство шрифтов, стиль шрифта, его размер, точку старта строки и формат строки. Для задания начертания (полужирный, курсив и т. п.) можно применить перечисление FontStyle. Однако для совместимости элемент перечисления необходимо явно привести к типу int. Объект класса StringFormat содержит всю необходимую информацию о формате надписи: центрирование по осям, расстояние между символами и строками и т. п. Обратите внимание: при отрисовке графического пути заданным пером р очерчиваются все находящиеся в нем объекты. Надпись очерчивается по периметру букв, поэтому буквы получились «пустыми». ^ Для рисования текста используется метод DrawText. Для прорисовки сначала создается объект Font со шрифтом типа Lucida Sans Unicode размером 15 единиц. Затем при помощи метода DrawString строка текста «Программирование на С#» выводится на экран. // создаем объект Graphics Graphics g = this.CreateGraphics (); // создаем объект Font Font titieFont = new Font("Lucida Sans Unicode", 15); // рисуем текст красным цветом g.DrawString("Программирование на С#",titleFont, new SolidBrush{Color.Red), point.X, point.Y); ^ Для рисования линий или контуров фигур
Graphics g = button1.CreateGraphics();
Pen myPen = new Pen(Color.Red, 2);
g.DrawLine(myPen, 1, 1, 45, 65); //линия g.DrawBezier(myPen, 15, 15, 30, 30, 45, 30, 87, 20); //кривая Безье g.DrawEllipse(myPen, Rectangle(33, 45, 40, 50)); //эллипс g.DrawRectangle(myPen, Rectangle(33, 45, 40, 50)); Для рисования закрашенных фигур
Graphics g = button1.CreateGraphics();
SolidBrush myBrush = new SolidBrush(Color.Red);
g.FillRectangle(myBrush, Rectangle(50, 50, 100, 100)); //прямоугольник g.FillPie(myBrush, Rectangle(110, 110, 300, 300), 0, 90); //четверть круга Для того, чтобы нарисовать линию, необходимо выполнить следующие действия: // создаем объект Реn Реп BlaсkРеn = new Pen (Color.Black, 3) ; // создаем объект Graphics Graphics g = this.CreateGraphics(); // рисуем линию g. DrawLine (BlaсkРеn, PreviousPoint, point); Для того, чтобы нарисовать эллипс, необходимо выполнить следующие действия: // создаем объект Pen Pen BlaсkРеn = new Pen (Color .Black, 3); // создаем объект Graphics Graphics g = this.CreateGraphics(); // рисуем эллипс g. DrawEllipse (BlaсkРеn, PreviousPoint.X, PreviousPoint.Y, point.X — PreviousPoint.X, point.Y — PreviousPoint.Y) ^ Выполнить задание согласно варианту:
Построить график функции согласно варианту задания. Предусмотреть ввод параметров функции. График должен занимать все отведенное для него место с указанием числовой разметки на осях координат. ^ 1. Улитка Паскаля: x=A·cos2(t)+B·cos(t) y=A·cos(t)·sin(t)+B·sin(t) Коэффициенты: A>B, B>0; Область определения функции: 0t<2·; Рассмотреть случаи, когда B2·A; AB. 2. Спирограф x=(A-B)·cos(t)+D·cos(w) y=(A-B)·sin(t)-D·sin(w), Коэффициенты: w=A·t/B, D Область определения функции: 0t2··n, n равно B, деленному на наибольший общий делитель (НОД) B и A. 3. Кардиоида x=A·cos(t)·(1+cos(t)) y=A·sin(t)·(1+cos(t)) Область определения функции: 0t<2·; Коэффициенты: A>0. 4. Эпициклоида x=(A+B)·cos(t)-A·cos((A+B)·t/A) y=(A+B)·sin(t)-A·sin((A+B)·t/A), Коэффициенты: A>0, B>0; Рассмотреть следующие случаи: а) если В/А есть целое, положительное число, то 0t<2·); в) если В/А=p/q, где p и q - целые положительные взаимно простые числа, то 0t<2·q·. ^ x=A+L·cos(t) y=A·tg(t)+L·sin(t), Область определения функции: при -/2 Коэффициенты: A>0, L>0; Рассмотреть случаи, когда LA, L=A. 6. “Бабочка” x=sin(A·t+B)·cos(C·t) y=sin(A·t+B)·sin(D·t), Область определения функции: 0t2·; Коэффициенты: A>0, B>0, C>0, D>0. ^ x =3·A·t/(t3+1) y=3·A·t2/(t3+1) Область определения функции: -∞ 8. Циклоида x=A·t-B·sin(t) y=A-B·cos(t) Область определения функции: 0t2·; Рассмотреть случаи: B>A, B 9. Гипоциклоида x=(B-A)·sin(A·t/B)-C·sin((B-A)·t/B) y=(B-A)·cos(A·t/b)+C·cos((B-A)·t/B), Область определения функции: 0t2·. 10. Трактриса x=A·(cos(t)+ln(tg(t/2)) y=A·sin(t) Область определения функции: 0t2·. 11. Цепная линия y=A·(ex/2+e-x/2)/2. Полярная система координат 12. Циссоида Диоклеса =A·(cos-1(φ)-cos(φ)). 13. Диаграмма направленности =L·(1+cos(φ))·sin(·A·sin(φ)/L)/(2··A·sin(φ)), A>0, 0φ<2·. 14. Крест "Cruciform" =2·A·sin-1(2φ). 15. Триссектриса =A·(4·cos(φ)-cos-1(φ)).
|