Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

  Раздел: Компьютерная документация -> Программирование -> Delphi / Pascal

 

Вывод графиков функций в Delphi

Изучая доступную литературу по программированию, которую я нашел в Интернете, а также некоторые программы, я пришел к выводу, что программисты то ли не осознают, то ли не хотят напрягаться на эту тему, и всё делают, как в школе учили. Строят графики, как на бумаге. Тем самым умаляя возможности компьютера. Оставляя те же недостатки метода построения, и даже усугубляя их.

Во первых вывод на экран - это вывод на дискретный носитель. Этот факт почти никак не учитывается. В тексте будет пояснено.

А сейчас я приведу пример программы из одного учебного электронного издания, автора я привести не могу, т.к. последний не указан.

unit Graf;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;
type
  TForm1 = class(TForm)
  procedure FormPaint(Sender: TObject);
  procedure FormResize(Sender: TObject);
  private
  { Private declarations }
  public
  { Public declarations }
  end;
var
  Form1: TForm1;

implementation

{$R *.dfm}
 Function f(x:real):real;
begin
f:=2*Sin(x)*exp(x/5);
end;
// строит график функции
procedure GrOfFunc;
var
x1,x2:real; // границы изменения аргумента функции
y1,y2:real; // границы изменения значения функции
x:real; // аргумент функции
y:real; // значение функции в точке х
dx:real; // приращение аргумента


l,b:integer; // левый нижний угол области вывода графика
w,h:integer; // ширина и высота области вывода графика
mx,my:real; // масштаб по осям X и Y 
x0,y0:integer; // точка - начало координат
begin // область вывода графика
l:=10; // X - координата левого верхнего угла
b:=Form1.ClientHeight-20; //У - координата левого верхнего угла
h:=Form1.ClientHeight-40; // высота
w:=Form1.Width-40; // ширина
x1:=0; // нижняя граница диапазона аргумента
x2:=25; // верхняя граница диапазона аргумента
dx:=0.01; // шаг аргумента

// найдем максимальное и минимальное значения
// функции на отрезке [x1,x2]

y1:=f(x1); // минимум
y2:=f(x1); //максимум
x:=x1;
repeat
y := f (x);
if y < y1 then y1:=y;
if y > y2 then y2:=y;
x:=x+dx; until (x >= x2);
// вычислим масштаб
my:=h/abs(y2-y1); // масштаб по оси Y
mx:=w/abs(x2-x1); // масштаб по оси X
x0:=1;
y0:=b-Abs(Round(y1*my)) ;
with form1.Canvas do
begin // оси
MoveTo(l,b);LineTo(l,b-h);
MoveTo(x0,y0);LineTo(x0+w,y0);
TextOut(l+5,b-h,FloatToStrF(y2,ffGeneral,6,3));
TextOut(l+5,b,FloatToStrF(y1,ffGeneral,6,3));
// построение графика
x:=x1; repeat
y:=f(x);
Pixels[x0+Round(x*mx),y0-Round(y*my)]:=clRed;
x:=x+dx;
until (x >= x2);
end;
end;


procedure TForm1.FormPaint(Sender: TObject); 
begin
GrOfFunc; end;
// изменился размер окна программы

procedure TForm1.FormResize(Sender: TObject); 
begin
// очистить форму
form1.Canvas.FillRect(Rect(0,0,ClientWidth,ClientHeight));
// построить график
GrOfFunc;
end;
end.

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

Теперь посмотрим, а сколько вычислений значений функции делает программа? В данном случае (25-0)/0.01=2500. Для любого прямоугольника вывода. Чем был обусловлен выбор шага dx? Скорее всего, непрерывностью линии графика. Который, кстати, так и остался прерывистым на некоторых участках, там, где функция меняется быстро. Борются с этим, уменьшая dx, причем чаще радикально - сразу в 10, и даже в 100 раз, доводя до 0.0001; меньше мне не приходилось встречать. А это 250000 вычислений функции. И графики все равно прерывистые. Благо компьютеры быстрые. Но вот если вычислять функцию, заданную неявно, то график будет строится помедленнее. Выберем прямоугольник вывода 600*400. Таким образом по горизонтали мы можем иметь только 600 значений. По оси У, соответственно, тоже. Вопрос: куда идут остальные 249400 результата вычислений? Часть идет на построение вертикальных отрезков прямых, соединяющих соседние ординаты, а львиную долю других поедает Round . Вот тебе и дискретный вывод. Отсюда вытекает, что функцию нужно считать в 600 точках, а отрезки вертикальных прямых можно нарисовать карандашом. И dx нужно выбирать в нашем случае (25-0)/600= 0,0416666. График получится самый качественный, какой только возможно получить. Затем, нет необходимости вычислять ее значение дважды .Можно раз, запомнив результат в массиве(Массив имеет размер не более разрешения монитора). В таких условиях скорость вывода не меняется.

Во-вторых, сам метод построения (вычисление значений функции с шагом dx) работает как фильтр, отсекая высокочастотные гармоники, т.е я хочу сказать, что если к функции f(x) добавить что-то вроде g(x)*sin(2*pi/dx*x), то результат вывода будет плачевным. Этот элемент никак не изменит предыдущий график. Хотя он может являться основным носителем информации о функции. И уж конечно очень непросто вывести на экран график дискретной функции (имеется в ввиду универсальными программами общего пользования, подобными приведенной). Если взять f(x)=2*Sin(x)*exp(x/5)+ exp(x*x)*sin(2*pi/dx*x), то данная программа второе слагаемое не заметит, хотя будет тратить время на расчет f(x)=2*Sin(x)*exp(x/5)* exp(x*x)*sin(2*pi/dx*x). А в этом случае график константы. Приведенная программа, как я упоминал, некорректно отобразит и его, но это же учебная программа. Поэтому претензий не предъявляем.

А вот если взять TAB MathGrapher 1.0 (распространена в Интернете) и просто ввести 5* Sin(200*pi*x), то мы получим чистый ноль. Вместо 5, понятно, можно написать любую функцию, да и вместо Sin(200*pi*x) любую периодическую с кратной частотой, и программа выдаст неверный график.

Это, как я уже писал, издержки метода построения. Как с этим бороться? Неэффективный и не исправляющий программу брать dx=0.0037 или что-то наподобие, тогда сложно будет подобрать период и натыкать автора(шутка). Очевидно, нужно, чтобы программа давала возможность рассматривать функцию на небольшом отрезке, с dx=(х2-х1)/w (ширина вывода в пикселях). Т.е. программа должна автоматически менять шаг с уменьшением отрезка. Что-то подобное я написал, в результате можно графическим методом решать умопомрачительные трансцендентные уравнения с точностью 10E-7 и выше за считанные минуты (х2, х1 нужно вводить вручную). Тем, кто над подобным не задумывался, код в руки, а пользователям хотелось бы порекомендовать: не берите программы, которые не меняют шаг. А то в ответственных случаях можно получить неверный график и попасть в затруднительное положение.

Автор: Алексей Легкунец
Источник: форум delphi



  Добавить закладку на материал: 


Ссылки по теме
Алгоритмы Сортировки. Часть 1
Введение в Delphi 8
Работа с реестром в Delphi
Delphi и ресурсы компьютера
Советы начинающим программировать на Delphi
Структуры и базы данных, методы сортировки

Вся документация Pascal и Delphi

 

Компьютерная документация от А до Я - Главная

 

 
Интересное в сети

Работа сантехником в сочи sochi.expertvremonte.ru.

 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.
 
Rambler's Top100