Данная глава посвящена графическим средствам языка. Рассмотрены основные процедуры и функции работы с графикой. Приведён пример построения графика функции.
При разработке проекта, в котором можно рисовать, в распоряжении программиста находится полотно (холст) — свойство Canvas, карандаш — свойство Pen, и кисть — свойство Brush.
Свойством Canvas обладают следующие компоненты:
Tform);TSringGrid);Timage);TPrinter).При рисовании компонента, обладающего свойством Canvas, сам компонент рассматривается как прямоугольная сетка, состоящая из отдельных точек, называемых пикселями. Положение пикселя характеризуется его вертикальной (X) и горизонтальной (Y) координатами. Левый верхний пиксель имеет координаты (0,0). Вертикальная координата возрастает сверху вниз, горизонтальная — слева направо. Общее количество пикселей по вертикали определяется свойством Height, а по горизонтали — свойством Weight. Каждый пиксель может иметь свой цвет. Для доступа к любой точке полотна используется свойство Pixels[X,Y]:TColor. Это свойство определяет цвет пикселя с координатами X(integer), Y(integer).
Изменить цвета любого пикселя полотна можно с помощью следующего оператора присваивания:
Компонент. Canvas. Pixels [X,Y] : = Color;
где Color — переменная или константа типа Tcolor.
| Константа | Цвет | Константа | Цвет |
|---|---|---|---|
clBlack |
Чёрный | clSilve |
Серебристый |
clMaroon |
Каштановый | clRed |
Красный |
clGreen |
Зелёный | clLime |
Салатовый |
clOlive |
Оливковый | clBlue |
Синий |
clNavy |
Тёмно-синий | clFuchsia |
Ярко-розовый |
clPurple |
Розовый | clAqua |
Бирюзовый |
clTeal |
Лазурный | clWhite |
Белый |
clGray |
Серый |
Определены следующие константы цветов (табл. 10.1).
Цвет любого пикселя можно получить с помощью следующего оператора присваивания:
Color :=Компонент. Canvas. Pixels [X,Y ];
где Color — переменная типа Tcolor.
Класс цвета точки Tcolor определяется как длинное целое longint. Переменные этого типа занимают в памяти четыре байта. Четыре байта переменных этого типа содержат информацию о долях синего (B), зелёного (G) и красного (R) цветов и устроены следующим образом: $00BBGGRR.
Для рисования используются методы класса TСanvas, позволяющие изобразить фигуру (линию, прямоугольник и т. д.) или вывести текст в графическом режиме, и три класса, определяющие инструменты вывода фигур и текстов:
TFont (шрифты);TPen (карандаш, перо);TBrush (кисть).Класс TFONT. Можно выделить следующие свойства соответствующего объекта Canvas.TFont:
Name (тип string) — имя используемого шрифта.Size (тип integer) — размер шрифта в пунктах (points). Пункт — это единица измерения шрифта, равная 0,353 мм или 1/72 дюйма.Style — стиль начертания символов, который может быть обычным, полужирным (fsBold), курсивным (fsItalic), подчёркнутым (fsUnderline) и перечёркнутым (fsStrikeOut). В программе можно комбинировать необходимые стили, например, чтобы установить стиль "полужирный курсив" необходимо написать следующий оператор:
Объект. Canvas. Font. Style : = [ fsItalic, fsBold ]Color (тип Tcolor) — цвет символов.Charset (тип 0..255) — набор символов шрифта. Каждый вид шрифта, определяемый его именем, поддерживает один или более наборов символов. В табл. 10.2 приведены некоторые значения Charset.| Константа | Значение | Описание |
|---|---|---|
ANSI_CHARSET |
0 | Символы ANSI |
DEFAULT_CHARSET |
1 | Задаётся по умолчанию. Шрифт выбирается только по его имени Name и размеру Size. Если описанный шрифт недоступен в системе, он будет заменён другим |
SYMBOL_CHARSET |
2 | Стандартный набор символов |
MAC_CHARSET |
77 | Символы Macintosh |
GREEK_CHARSET |
161 | Греческие символы |
RUSSIAN_CHARSET |
204 | Символы кириллицы |
EASTEUROPE_CHARSET |
238 | Включает диалектические знаки (знаки, добавляемые к буквам и характеризующие их произношение) для восточно-европейских языков |
Класс TPEN. Карандаш (перо) используется как инструмент для рисования точек, линий, контуров геометрических фигур. Основные свойства объекта Canvas.TPen:
Color (тип Tcolor) — определяет тип линии;Width (тип Integer) — задаёт толщину линии в пикселях;Style — даёт возможность выбрать вид линии. Это свойство может принимать значение, указанное в таблице 10.3.
| Значение | Описание |
|---|---|
psSolid |
Сплошная линия |
psDash |
Штриховая линия |
psDot |
Пунктирная линия |
psDashDot |
Штрихпунктирная линия |
psDashDodDot |
Линия, чередующая штрих и два пунктира |
psClear |
Нет линии |
Mode — определяет, каким образом взаимодействуют цвета пера и полотна. Выбор значения этого свойства позволяет получать различные эффекты. Возможные значения Mode приведены в табл. 10.4. По умолчанию вся линия вычерчивается цветом, определяемым значением Pen.Color, но можно определять инверсный цвет линии по отношению к цвету фона. В этом случае независимо от цвета фона, даже если цвет линии и фона одинаков, линия будет видна.| Режим | Операция | Цвет пикселя |
|---|---|---|
pmBlack |
Black | Всегда чёрный |
pmWhite |
White | Всегда белый |
pmNop |
— | Неизменный |
pmNot |
Not Screen | Инверсный цвет по отношению к цвету фона |
pmCopy |
Pen | Цвет, указанный в свойствах Color пера Pen (это значение принято по умолчанию) |
pmNotCopy |
Not Pen | Инверсия цвета пера |
pmMergePenNot |
Pen or Not Pen | Дизъюнкция цвета пера и инверсного цвета фона |
pmMaskPenNot |
Pen and Not Screen | Конъюнкция цвета пера и инверсного цвета фона |
pmMergeNotPen |
Not Pen or Screen | Дизъюнкция цвета фона и инверсного цвета пера |
PmMaskNotPen |
Not Pen and Screen | Конъюнкция цвета фона и инверсного цвета пера |
pmMerge |
Pen or Screen | Дизъюнкция цвета пера и цвета фона |
pmNotMerge |
Not (Pen or Screen) | Инверсия режима pmMerge |
pmMask |
Pen and Screen | Конъюнкция цвета пера и цвета фона |
pmNotMask |
Not (Pen and Screen) | Инверсия режима pmMask |
pmXor |
Pen xor Screen | Операция xor над цветом пера и цветом фона |
pmNotXor |
Not (Pen xor Screen) | Инверсия режима pmXor |
Класс TBRUSH. Кисть (Canvas.Brush) используется методами, обеспечивающими вычерчивание замкнутых фигур для заливки. Кисть обладает двумя основными свойствами:
Color (тип Tcolor) — цвет закрашивания замкнутой области;Style (тип TBrushStyle) — определяет стиль заполнения области (bsSolid — сплошное заполнение, bsClear — прозрачное, bsHorizontal — горизонтальные линии, bsVertical — вертикальные линии, bsFDiagonal, bsBDiagonal — диагональные линии, bsCross — решётка, bsDiagCross — диагональная решетка).Класс TCANVAS. Этот класс является основным инструментом для рисования графики. Рассмотрим его наиболее часто используемые методы.
procedure MoveTo(X, Y : integer );
Метод MoveTo изменяет текущую позицию пера на позицию, заданную точкой (X,Y). Текущая позиция хранится в переменной PenPos типа Tpoint. Определение типа TPoint следующее:
type TPoint =record X : longint; Y: longint; end;
Текущую позицию пера можно считывать с помощью свойства PenPos следующим образом:
X:=PenPos.X; Y:=PenPos.Y;
procedure LineTo (X, Y : integer);
Метод LineTo соединяет прямой линией текущую позицию пера и точку с координатами (X,Y). При этом текущая позиция пера перемещается в точку с координатами (X,Y).
Рассмотрим работу процедуры на примере. Расположим на форме кнопку и рассмотрим процедуру обработки события TForm1.Button1Click, которая рисует прямые линии:
procedure TfForm1. Button1Click ( Sender : TObject ) begin Form1. Canvas. LineTo ( 30, 50 ); end;
В результате щелчка по кнопке на форме будет нарисована прямая линия, соединяющая точку с координатами (0,0) и точку с координатами (30,50). При повторном щелчке по кнопке процедура продолжит рисовать эту же линию.
Теперь перепишем процедуру обработки события следующим образом:
procedure TForm1. Button1Click ( Sender : TObject ) begin Form1. Canvas. LineTo ( Canvas. PenPos. x+30, Canvas. PenPos. y +50); end;
При первом щелчке по кнопке на экране прорисуется аналогичная линия. Но при повторном щелчке процедура рисует линию, которая соединяет текущую точку с точкой, получившейся из текущей добавлением к координате X числа 30, а к координате Y — числа 50. Т. е. при повторном щелчке по кнопке процедура соединяет прямой линией точки (30,50) и (60,100). При третьем щелчке по кнопке будут соединяться прямой линией точки (60,100) и (90,150) и т. д.
procedure PolyLine ( const Points array of TPoint );
Метод PolyLine рисует ломаную линию, координаты вершин которой определяются массивом Points.
Рассмотрим работу процедуры на примере. Расположим на форме кнопки Рисовать и Выход и запишем следующие операторы процедур обработки события:
procedure TForm1. Button1Click ( Sender : TObject ); var temp : array [ 1.. 2 5 ] of TPoint; i : byte; j : integer; begin j : = 1; for i :=1 to 25 do begin //вычисление координат вершин ломаной линии temp [ i ]. x:=25+( i _ 1) _ 10; temp [ i ]. y:=150 _ j _ ( i _ 1) _ 5; j :=- j; end; Form1. Canvas. Polyline ( temp ); end; procedure TForm1. Button2Click ( Sender : TObject ); begin Form1. Close; end;
После запуска программы и щелчка по кнопке Рисовать окно формы будет выглядеть, как на рисунке 10.1.
procedure Ellipse (X1, Y1, X2, Y2 : integer );
Метод Ellipse вычерчивает на холсте эллипс или окружность. X1, Y1, X2, Y2 — это координаты прямоугольника, внутри которого вычерчивается эллипс. Если прямоугольник является квадратом, то вычерчивается окружность.
procedure Arc (X1, Y1, X2, Y2, X3, Y3, X4, Y4 : integer );
Метод Arc вычерчивает дугу эллипса. X1, Y1, X2, Y2 — это координаты, определяющие эллипс, частью которого является дуга; X3, Y3 — координаты, определяющие начальную точку дуги; X4, Y4 — координаты, определяющие конечную точку дуги. Дуга рисуется против часовой стрелки.
procedure Rectangle (X1, Y1, X2, Y2 : integer );
Метод Rectangle рисует прямоугольник. X1, Y1, X2, Y2 — координаты верхнего левого и нижнего правого углов прямоугольника.
(рис 10.1) Пример использования процедуры PolyLine
procedure RoundRect (X1, Y1, X2, Y2, X3, Y3 : integer );
Это метод вычерчивания прямоугольника со скруглёнными углами. X1, Y1, X2, Y2 — координаты верхнего левого и нижнего правого углов прямоугольника, а X3, Y3 — размер эллипса, одна четверть которого используется для вычерчивания скругленного угла.
procedure PolyGon ( const Points array of TPoint );
Метод PolyGon рисует замкнутую фигуру (многоугольник) по множеству угловых точек, заданному массивом Points. При этом первая точка соединяется прямой линией с последней. Этим метод PolyGon отличается от метода Poliline, который не замыкает конечные точки. Рисование осуществляется текущим пером Pen, а внутренняя область фигуры закрашивается текущей кистью Brush.
procedure Pie (X1, Y1, X2, Y2, X3, Y3, X4, Y4 : integer );
Метод Pie рисует замкнутую фигуру — сектор окружности или эллипса — с помощью текущих параметров пера Pen, внутренняя область закрашивается текущей кистью Brush. Точки (X1,Y1) и (X2,Y2) задают прямоугольник, описывающий эллипс. Начальная точка дуги определяется пересечением эллипса с прямой, проходящей через его его центр и точку (X3,Y3). Конечная точка дуги определяется пересечением эллипса с прямой, проходящей через его центр и точку (X4,Y4). Дуга рисуется против часовой стрелки от начальной до конечной точки. Рисуются прямые, ограничивающие сегмент и проходящие через центр эллипса и точки (X3,Y3) и (X4,Y4).
(рис 10.2) Пример использования методов рисования фигур
Создадим форму, установим ей размеры Heigth — 500, Weight — 500. Внизу разместим кнопку, зададим ей свойство Caption — "Рисовать". При запуске программы и щелчке по этой кнопке на форме прорисуются различные фигуры (см. рис. 10.2). Ниже приведён листинг программы, демонстрирующий работу перечисленных методов. Результат работы программы приведен на рис. 10.2.
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics,
Dialogs, StdCtrls;
type
{ TForm1 }
TForm1 = class (TForm)
Button1 : TButton;
procedure Button1Click ( Sender : TObject );
private
{ private declarations }
public
{ public declarations }
end;
var
Form1 : TForm1;
implementation
{ TForm1 }
procedure TForm1. Button1Click ( Sender : TObject );
var t : array [ 1.. 5 ] of TPoint;
begin
//рисование линии
Form1. Canvas. LineTo ( 500, 500 );
//изменяем цвет и толщину линии
Form1. Canvas. Pen. Color := clMaroon;
Form1. Canvas. Pen. Width:= 5;
//рисование прямоугольника
Form1. Canvas. R e c tan gle ( 50, 50, 200, 200 );
Form1. Canvas. Pen. Color := clolive;
//рисование эллипса
Form1. Canvas. Ellipse ( 50, 50, 100, 200 );
//рисование прямоугольника со скруглёнными углами
Form1. Canvas. RoundRect ( 250, 250, 400, 400, 30, 30 );
//рисование сектора окружности
Form1. Canvas. Pie ( 300, 300, 400, 400, 350, 350, 500, 500 );
//формирование массива координат вершин пятиугольника
t [ 1 ]. x :=250; t [ 1 ]. y := 10;
t [ 2 ]. x :=350; t [ 2 ]. y := 15;
t [ 3 ]. x :=400; t [ 3 ]. y := 50;
t [ 4 ]. x :=300; t [ 4 ]. y :=150;
t [ 5 ]. x :=250; t [ 5 ]. y :=100;
Form1. Canvas. Polygon ( t );
Form1. Canvas. TextOut ( 10, 10, ’это вывели текст ’ );
end;
initialization
{$I unit1.lrs}
end.
procedure TextOut (X, Y : integer; const Text : String );
Эта функция пишет строку текста Text, начиная с позиции с координатами (X,Y). Текущая позиция PenPos пера Pen перемещается в конец выведенного текста. Надпись выводится в соответствии с текущими установками шрифта Font, фон надписи определяется установками текущей кисти. Для выравнивания позиции текста на канве можно использовать методы, позволяющие определить высоту и длину текста в пикселях — TextExtent, TextHeight и TextWidth. Рассмотрим эти функции.
function TextExtent ( const Text : String ) : Tsize;
Эта функция возвращает структуру типа Tsize, содержащую длину и высоту в пикселях текста Text, который предполагается написать на канве текущим шрифтом.
type Tsize = record cx : longint; cx : longint; end;
function TextHeight ( const Text : String ) : integer;
Функция возвращает высоту в пикселях текста Text, который предполагается написать на канве текущим шрифтом.
function TextWidth ( const Text : String ) : integer;
Функция возвращает длину в пикселях текста Text, который предполагается написать на канве текущим шрифтом. Это позволяет перед выводом текста на канву определить размер надписи и расположить её и другие элементы изображения наилучшим образом.
Если цвет кисти в момент вывода текста отличается от того, которым закрашена канва, то текст будет выведен в цветной прямоугольной рамке, но её размеры будут точно равны размерам надписи.
Мы рассмотрели основные функции рисования. Теперь можно перейти непосредственно к рисованию. Но перед этим следует заметить, что если вы свернёте окно с графикой, а затем его восстановите, то картинка на форме исчезнет. Изменение размеров окна также может испортить графическое изображение в нём. Для решения этой проблемы существуют процедуры обработки событий Объект.FormPaint и Объект.FormResize. Процедура Объект.FormPaint выполняется после появления формы на экране, а процедура Объект.FormResize — после изменения размера формы. Следовательно, все операторы рисования нужно помещать внутрь Объект.FormPaint и дублировать в процедуре Объект.FormResize.
Алгоритм построения графика непрерывной функции $$y = f (x)$$ на отрезке $$[a; b]$$ состоит в следующем: необходимо построить точки $$(x_i, f (x_i ))$$ в декартовой системе координат и соединить их прямыми линиями. Координаты точек определяются по следующим формулам:
$$hx = (b - a)/N,$$где $$N$$ — количество отрезков на отрезке $$[a; b]$$.
$$x_i = a + (i - 1)hx; y_i = f (x_i ),$$где $$i = 0,..., N$$.
Чем больше точек будет изображено, тем более плавным будет построенный график.
При переносе этого алгоритма на форму или другой компонент Lazarus учитывает размеры и особенности компонента (ось ОX направлена слева направо, её координаты лежат в пределах от 0 до Width; ось OY направлена вниз, её координаты находятся в пределах от 0 до Height). Значения координат X и Y должны быть целыми.
Необходимо пересчитать все точки из "бумажной" системы координат ($$X$$ изменяется в пределах от $$a$$ до $$b$$, $$Y$$ изменяется от минимального до максимального значения функции) в "
Tform, Timage, Tprinter и т. д.
Для преобразования координаты $$X$$ в координату $$U$$ построим линейную функцию $$cX + d$$, которая переведёт точки из интервала $$(a; b)$$ в точки интервала $$(X_0, Width - X_k)$$
Решив её, найдём коэффициенты $$c, d$$:
$$\left\{\begin{aligned} d = X_0 - c \times a \\ c = (Width - X_k - X_0)/(b - a) \end{aligned}\right.$$Для преобразования координаты $$Y$$ в координату $$V$$ построим линейную функцию $$V = gY + h$$. Точка $$min$$ "бумажной" системы координат перейдет в точку $$Height - Y_k$$ "компонентной", а точка $$max$$ — в точку $$Y_0$$. Для нахождения коэффициентов $$g$$ и $$h$$ решим систему линейных алгебраических уравнений:
$$\left\{\begin{aligned} g \times min + h = Heignt - Y_k \\ g \times max + h = Y_0 \end{aligned}\right.$$Её решение позволит найти нам коэффициенты $$g$$ и $$h$$.
$$\left\{\begin{aligned} h = Y_0 - g \times max \\ g = (Height - Y_k - Y_0)/(min - max) \end{aligned}\right.$$Перед описанием алгоритма построения графика давайте уточним формулы для расчёта коэффициентов $$c, d, g$$ и $$h$$. Дело в том, что Width — это ширина компонента с учётом рамок слева и справа, а Height — полная высота компонента с учётом рамки, а если в качестве компонента будет использоваться форма, то необходимо учесть заголовок окна. Однако для изображения графика нам нужны вертикальные и горизонтальные размеры компонент без учёта рамок и заголовка. Эти размеры хранятся в свойствах ClientWidth (ширина клиентской области компонента без учёта ширины рамки) и ClientHeight (высота клиентской области компонента, без учёта ширины рамки и ширины заголовка) компонента. Поэтому для расчёта коэффициентов $$c, d, g$$ и $$h$$ логичнее использовать следующие формулы:
Алгоритм построения графика на экране монитора можно разделить на следующие этапы:
max) и минимальное (min) значения $$Y$$.LineTo.При построении графиков нескольких непрерывных функций вместо массивов $$Y$$ и $$V$$ рационально использовать матрицы размером $$k \times n$$, где $$k$$ — количество функций. Элементы каждой строки матриц являются координатами соответствующего графика в "бумажной" ($$Y$$) и "компонентной" ($$V$$) системах координат.
Блок-схема алгоритма изображения графика представлена на рис. 10.3, блок-схема построения графиков k непрерывных функций на рис. 10.4.
Рассмотрим поэтапно каждую схему.
Для рис. 10.3 первый этап алгоритма представлен в блоках 2 и 3. Второй этап реализуется в блоках 4—13. Коэффициенты третьего этапа рассчитываются в блоке 14. В блоках 15—16 формируются массивы значений $$U$$ и $$V$$ "компонентной системы координат (этап 4). Блоки 17—19 — это вывод графиков на экран, и блок 20 предназначен для шестого этапа.
(рис 10.3) Блок-схема алгоритма построения графика функции
Для второй схемы (рис. 10.4) реализация второго этапа представлена в блоках 4—15. В блоке 16 рассчитываются коэффициенты $$c, d, g$$ и $$h$$. В блоках 17—20 формируются массивы четвёртого этапа. Блоки 21—24 предназначены для вывода графиков, а блок 25 — для построения осей.
ЗАДАЧА 10.1. Построить график функции f (x) на интервале [a, b].Функция задана следующим образом:
$$f(x) = \left\{\begin{array}{rl} \sin(x/2), \text{если } x \le 0 \\ \sqrt{(1+x)/3}, \text{если } x > 0 \end{array}\right.$$
Создадим новый проект, изменим высоту и ширину формы до размеров, достаточных для отображения на ней графика. Например, можно установить следующие свойства: Width — 800, Height — 700. Разместим на форме кнопку и компонент класса TImage. Объект TImage1 — это растровая картинка, которая будет использоваться для отображения графика после щелчка по кнопке Button1. Размеры растровой картинки сделаем чуть меньше размеров формы.
(рис 10.4) Блок-схема алгоритма построения графика нескольких функции
Установим в качестве свойства формы Caption сроку "График функции".
Чтобы избавиться от проблемы перерисовки будущего графика при изменении размера формы, запретим изменение формы и уберём кнопки минимизации и максимизации окна. Свойство формы BorderStyle определяет внешний вид и поведение рамки вокруг окна формы. Для запрета изменения формы установим значение свойства BorderStyle в bsSingle — это значение определяет стандартную рамку вокруг формы и запрещает изменение размера формы. Чтобы убрать кнопки минимизации и максимизации формы, установим её свойства BolderIcons.BiMaximize и BolderIcons.BiMinimize в False.
Для кнопки установим свойство Caption — фразу "Построить график".
(рис 10.5) Окно формы после установки свойств
После установки всех описанных свойств окно формы должно стать подобным представленному на рис. 10.5.
Ввод интервала $$a$$ и $$b$$ выполним с помощью запроса в момент создания формы (в методе инициализации формы $$FormCreate$$). Ниже приведён листинг модуля проекта рисования графика с комментариями:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics,
Dialogs, ExtCtrls, StdCtrls;
//объявление функции, которая задаётся
//математически для построения
function f ( x : real ) : real;
//объявление функции, которая изображает
//график функции на компоненте
procedure Graphika ( a, b : real );
type
{ TForm1 }
TForm1 = class (TForm)
Button1 : TButton;
Image1 : TImage;
procedure Button1Click ( Sender : TObject );
procedure FormCreate ( Sender : TObject );
private
{ private declarations }
public
{ public declarations }
end;
var
Form1 : TForm1;
//объявление переменных
//x0, xk, y0, yk - отступы от границ компонента слева
//справа, сверху и снизу
//x, y - массивы, определяющие координаты точек графика
//в "бумажной" системе координат
//u, v массивы, определяющие координаты точек графика
//в "компонентной" системе координат
//N - количество точек
x0, y0, xk, yk, a, b : real;
x, y : array [ 0.. 1000 ] of real;
u, v : array [ 0.. 1000 ] of integer;
N : integer;
implementation
//функция, которая будет изображена на компоненте Image1
function f ( x : real ) : real;
begin
if x<=0 then Result := sin ( x /2)
else Result := sqrt ((1+x ) / 3 );
end;
//функция, которая рисует график
//заданной функции на компоненте Image1
procedure Graphika ( a, b : real );
//Kx+1 - количество линий сетки, перпендикулярных оси ОХ
//Ky+1 - количество линий сетки, перпендикулярных оси ОY
const Kx=5; Ky=5;
var
dx, dy, c, d, g, h, max, min : real;
i, tempx, tempy : integer;
s : string;
begin
//вычисление шага изменения по оси Х
h :=(b-a ) / (N-1);
//формирование массивов x и y
x [ 0 ] : = a;
y [ 0 ] : = f ( x [ 0 ] );
for i :=1 to N do
begin
x [ i ] : = x [ i - 1]+h;
y [ i ] : = f ( x [ i ] );
end;
//нахождение максимального и минимального значений массива Y
max:=y [ 0 ]; min:=y [ 0 ];
for i :=1 to N do
begin
if y [ i ]>max then max:=y [ i ];
if y [ i ]<min then min:=y [ i ];
end;
//формирование коэффициентов пересчёта из "бумажной" в
//"компонентную" систему координат
c :=(Form1. Image1. ClientWidth - x0-xk ) / ( b-a );
d:=x0-c * x [ 0 ];
g :=(Form1. Image1. ClientHeight -y0-yk ) / ( min- max );
h:=yk-g * max;
//формирование массивов точек в экранной системе координат
for i :=0 to N do
begin
u [ i ] : = trunc ( c * x [ i ]+d );
v [ i ] : = trunc ( g * y [ i ]+h );
end;
Form1. Image1. Canvas. Color := clGray;
Form1. Image1. Canvas. Pen. Mode:= pmNot;
//рисование графика функции на компоненте Image1
Form1. Image1. Canvas. MoveTo( u [ 0 ], v [ 0 ] );
Form1. Image1. Canvas. Pen. Width:= 2;
Form1. Image1. Canvas. Pen. Color := clGreen;
for i :=1 to N do
Form1. Image1. Canvas. LineTo ( u [ i ], v [ i ] );
Form1. Image1. Canvas. Pen. Width:= 1;
Form1. Image1. Canvas. Pen. Color := clBlack;
//рисование осей координат, если они попадают
//в область графика
Form1. Image1. Canvas. MoveTo( trunc ( x0 ), trunc ( h ) );
if ( trunc ( h)>yk ) and
( trunc ( h)< trunc ( Form1. Image1. ClientHeight - y0 ) )
then
Form1. Image1. Canvas. LineTo ( trunc ( Form1. Image1. ClientWidth
-xk ), trunc ( h ) );
Form1. Image1. Canvas. MoveTo( trunc ( d ), trunc ( yk ) );
if ( trunc ( d)>x0 ) and
( trunc ( d)< trunc ( Form1. Image1. ClientWidth -xk ) )
then
Form1. Image1. Canvas. LineTo ( trunc ( d ),
trunc ( Form1. Image1. ClientHeight - y0 ) );
//рисование линий сетки
//вычисление расстояния между линиями сетки в "компонентной" системе
//координат,перпендикулярными оси ОХ
dx :=(Form1. Image1. ClientWidth - x0-xk )/KX;
//выбираем тип линии для линий сетки
for i :=0 to KX do
begin
//первую и последнюю линии сетки рисуем обычной
//сплошной линией
if ( i =0) or ( i=KX) then
Form1. Image1. Canvas. Pen. Style := psSolid
//остальные рисуем пунктирными линиями
else
Form1. Image1. Canvas. Pen. Style := psDash;
//рисование линии сетки, перпендикулярной оси ОХ
Form1. Image1. Canvas. MoveTo( trunc ( x0+i * dx ), trunc ( yk ) );
Form1. Image1. Canvas. LineTo ( trunc ( x0+i * dx ),
trunc ( Form1. Image1. ClientHeight - y0 ) );
end;
//вычисление расстояния между линиями сетки в "компонентной" системе
//координат,перпендикулярными оси ОY
dy :=(Form1. Image1. ClientHeight -y0-yk )/KY;
for i :=0 to KY do
begin
//первую и последнюю линии сетки рисуем обычной сплошной линией
if ( i =0) or ( i=KY) then
Form1. Image1. Canvas. Pen. Style := psSolid
//остальные рисуем пунктирными линиями
else
Form1. Image1. Canvas. Pen. Style := psDash;
//рисование линии сетки, перпендикулярной оси ОY
Form1. Image1. Canvas. MoveTo( trunc ( x0 ), trunc ( yk+i * dy ) );
Form1. Image1. Canvas. LineTo ( trunc ( Form1. Image1. ClientWidth
-xk ), trunc ( yk+i * dy ) );
end;
Form1. Image1. Canvas. Pen. Style := psSolid;
//вывод подписей под осями
//определяем dx - расстояние между выводимыми
//под осью ОХ значениями
dx :=(b-a )/KX;
tempy:= trunc ( Form1. Image1. ClientHeight -y0 +10);
for i :=0 to KX do
begin
//преобразование выводимого значения в строку
Str ( a+i * dx : 5 : 2, s );
//вычисление х-координаты выводимого под осью ОХ значения
//в "компонентной" системе
tempx:= trunc ( x0+i * ( Form1. Image1. ClientWidth -x0-xk )/KX) -10;
//вывод значения под осью ОХ
Form1. Image1. Canvas. TextOut ( tempx, tempy, s );
end;
if ( trunc ( d)>x0 ) and ( trunc ( d)<Form1. Image1. ClientWidth -xk )
then
Form1. Image1. Canvas. TextOut ( trunc ( d) -5,tempy, ’ 0 ’ );
//определяем dy - расстояние между выводимыми левее
//оси ОY значениями
dy :=(max _min )/KY;
tempx : = 5;
for i :=0 to KY do
begin
//преобразование выводимого значения в строку
S t r (max -i * dy : 5 : 2, s );
//вычисление y-координаты выводимого левее оси ОY
//значения в "компонентной" системе
tempy:= trunc ( yk-5+i * ( Form1. Image1. ClientHeight
-y0-yk )/KY);
//вывод значения левее оси ОY
Form1. Image1. Canvas. TextOut ( tempx, tempy, s );
end;
if ( trunc ( h)>yk ) and
( trunc ( h)<Form1. Image1. ClientHeight -y0 )
then
Form1. Image1. Canvas. TextOut ( tempx+10, trunc ( h) -5, ’ 0 ’ );
tempx:= trunc ( x0+i * ( Form1. Image1. ClientWidth - x0-xk ) / 2 );
Form1. Image1. Canvas. TextOut ( tempx, 10, ’График функции ’ );
end;
{ TForm1 }
procedure TForm1. FormCreate ( Sender : TObject );
var s : string;
kod : integer;
begin
N:=100;
x0 := 40; xk := 40;
y0 := 40; yk := 40;
repeat
s := InputBox ( ’График непрерывной функции ’, ’Введите левую ’,
’границу ’, ’ -10 ’ );
Val ( s, a, kod );
until kod =0;
repeat
s := InputBox ( ’График непрерывной функции ’, ’Введите правую ’,
’границу ’, ’ 10 ’ );
Val ( s, b, kod );
until kod =0;
end;
procedure TForm1. Button1Click ( Sender : TObject );
begin
Graphika ( a, b );
end;
initialization
{$I unit1.lrs}
end.
При запуске проекта появится запрос ввода левой (рисунок 10.6) и правой (рисунок 10.7) границ интервала.
(рис 10.6) Окно ввода левой границы интервала
(рис 10.7) Окно ввода правой границы интервала
После этого появится окно формы с кнопкой График. После щелчка по кнопке на форме прорисуется график функции (рис. 10.8).
(рис 10.8) Окно с прорисованным графиком
Перевёрнута последняя страница книги. Что теперь? Авторы надеются, что знакомство с языком Free Pascal будет только первым этапом в изучении программирования. Желание читателя что-то исправить в книге: переписать приведённые в ней программы, предложить более простые и быстро работающие алгоритмы, написать свои программы и модули, будет лучшей благодарностью авторам. Если у Вас, читатель, появилось подобное желание, то мы выполнили свою задачу — научили Вас основам программирования.
Следующим этапом в освоении программирования будет разработка своих алгоритмов и написание реально работающих программ для различных операционных систем.
Мы надеемся, что это — только первая книга, посвящённая программированию. Думаем, что наша книга положит начало новой серии книг, посвящённой программированию в Linux. Следующей может стать книга, посвящённая решению более сложных задач на Free Pascal.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.