Неправильное вычисление масштабного коэффициента при построении графика - Turbo Pascal
Формулировка задачи:
В большинстве примеров построения графиков масштабный коэффициент вычисляют по формуле ky=height/abs(y_max-y_min). Что эта формула не подходит для случаев когда y_min и y_max не симметричны относительно оси абсцисс можно убедиться на примере.
w = 400, h = 640
a = - 5, b = 5
f(x) = x + 2
X0 = 200, Y0 = 320
y_min = -3, y_max = 7
kx = 400/(5 + 5) = 40
ky = 640/(3 + 7) = 64
Формулы для экранных координат:
X = X0 + x·kx
Y = Y0 + y·ky
Получаем:
X_min = 200 + 40·(-5) = 0
X_max = 200 + 40·5 = 400
Y_min = 320 - 64·(-3) = 512
Y_max = 320 - 64·7 = -128
Очевидно, что последние значения неправильны. Если вычислить ky «по бумажке», Y_min = 440
Y_max = 40,
то имеем ky = 400/10 = 40
Тогда и график строится правильно.
Пример неправильного и правильного (зелёный) графиков.
Но вот вопрос: как узнать правильный коэффициент???
Решение задачи: «Неправильное вычисление масштабного коэффициента при построении графика»
textual
Листинг программы
{программа построения дух графиков на одной оси координат}
program P;
uses
Graph,
WinCRT;
function f1(X: real): real;
begin
f1 := 16 * sqr(X);
end;
function f2(X: real): real;
begin
f2 := 1 / 7 * sqr(X);
end;
var
GraphDevice, GraphMode: integer;
ScreenXstart, ScreenXfinish, ScreenYstart, ScreenYfinish: integer;
ScaleX, ScaleY: real;
Xstart, Xfinish, Ystart, Yfinish: real;
X, Y, dX: real;
Xscreen, Yscreen: integer;
IsNextVisiblePixel: boolean;
begin
{параметры графиков}
Xstart := -0.05;
Xfinish := 0.05;
Ystart := 0.0;
Yfinish := 0.0010;
{инициализация графики}
GraphDevice := Detect;
GraphMode := Detect;
InitGraph(GraphDevice, GraphMode, '');
if GraphResult <> grOk then
begin
writeln('Error');
Exit;
end;
{от края экрана отступим по 10% экрана}
ScreenXstart := GetMaxX div 10;
ScreenXfinish := GetMaxX - ScreenXstart;
ScreenYstart := GetMaxY div 10;
ScreenYfinish := GetMaxY - ScreenYstart;
{расчёт масштабных коэффициентов}
ScaleX := (ScreenXfinish - ScreenXstart) / (Xfinish - Xstart);
ScaleY := (ScreenYfinish - ScreenYstart) / (Yfinish - Ystart);
{построение осей координат}
SetColor(7);
MoveTo(ScreenXstart, ScreenYstart);
LineTo(ScreenXstart, ScreenYfinish);
LineTo(ScreenXfinish, ScreenYfinish);
LineTo(ScreenXfinish, ScreenYstart);
LineTo(ScreenXstart, ScreenYstart);
MoveTo((ScreenXfinish + ScreenXstart) div 2, ScreenYstart);
LineTo((ScreenXfinish + ScreenXstart) div 2, ScreenYfinish);
{построение 1-го графика}
SetColor(5);
IsNextVisiblePixel := False;
X := Xstart;
dX := (Xfinish - Xstart) / 1000;
while X <= Xfinish do
begin
Y := f1(X);
Xscreen := round((X - Xstart) * ScaleX) + ScreenXstart;
Yscreen := -round((Y - Ystart) * ScaleY) + ScreenYfinish;
if (Xscreen >= ScreenXstart) and (Xscreen <= ScreenXfinish) and
(Yscreen > ScreenYstart) and (Yscreen < ScreenYfinish) then
begin
if IsNextVisiblePixel then
LineTo(Xscreen, Yscreen)
else
MoveTo(Xscreen, Yscreen);
IsNextVisiblePixel := True;
end
else
IsNextVisiblePixel := False;
X := X + dX;
end;
{построение 2-го графика}
SetColor(4);
IsNextVisiblePixel := False;
X := Xstart;
dX := (Xfinish - Xstart) / 1000;
while X <= Xfinish do
begin
Y := f2(X);
Xscreen := round((X - Xstart) * ScaleX) + ScreenXstart;
Yscreen := -round((Y - Ystart) * ScaleY) + ScreenYfinish;
if (Xscreen >= ScreenXstart) and (Xscreen <= ScreenXfinish) and
(Yscreen > ScreenYstart) and (Yscreen < ScreenYfinish) then
begin
if IsNextVisiblePixel then
LineTo(Xscreen, Yscreen)
else
MoveTo(Xscreen, Yscreen);
IsNextVisiblePixel := True;
end
else
IsNextVisiblePixel := False;
X := X + dX;
end;
ReadKey;
end.
Объяснение кода листинга программы
- В функции
f1коэффициент масштабирования16умножается на квадрат аргументаX. - В функции
f2коэффициент масштабирования1/7умножается на квадрат аргументаX. - Переменные
GraphDevice,GraphModeинициализируются функциейDetect, которая возвращает детектированный устройство для графика. - Переменные
ScreenXstart,ScreenXfinish,ScreenYstartиScreenYfinishвычисляются как 10% от максимальных значенийXиY. - Коэффициенты масштабирования
ScaleXиScaleYвычисляются как отношение максимальных значенийScreenXиScreenYк максимальным значениямXиY. - Оси координат строятся с помощью функции
MoveToиLineTo. - Первый график строится с помощью функции
f1. - Второй график строится с помощью функции
f2. - Переменная
IsNextVisiblePixelиспользуется для отслеживания следующего видимого пикселя при построении графика. - Переменные
X,YиdXиспользуются для вычисления текущего положенияXиYи изменения их значения на единицуdXпри каждом шаге построения графика. - Переменные
XscreenиYscreenиспользуются для вычисления координат пикселей на экране для каждого шага построения графика.