Неправильное вычисление масштабного коэффициента при построении графика - 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
Листинг программы
  1. {программа построения дух графиков на одной оси координат}
  2. program P;
  3.  
  4. uses
  5.   Graph,
  6.   WinCRT;
  7.  
  8.   function f1(X: real): real;
  9.   begin
  10.     f1 := 16 * sqr(X);
  11.   end;
  12.  
  13.   function f2(X: real): real;
  14.   begin
  15.     f2 := 1 / 7 * sqr(X);
  16.   end;
  17.  
  18. var
  19.   GraphDevice, GraphMode: integer;
  20.   ScreenXstart, ScreenXfinish, ScreenYstart, ScreenYfinish: integer;
  21.   ScaleX, ScaleY: real;
  22.   Xstart, Xfinish, Ystart, Yfinish: real;
  23.   X, Y, dX: real;
  24.   Xscreen, Yscreen: integer;
  25.   IsNextVisiblePixel: boolean;
  26. begin
  27.   {параметры графиков}
  28.   Xstart  := -0.05;
  29.   Xfinish := 0.05;
  30.   Ystart  := 0.0;
  31.   Yfinish := 0.0010;
  32.   {инициализация графики}
  33.   GraphDevice := Detect;
  34.   GraphMode := Detect;
  35.   InitGraph(GraphDevice, GraphMode, '');
  36.   if GraphResult <> grOk then
  37.   begin
  38.     writeln('Error');
  39.     Exit;
  40.   end;
  41.   {от края экрана отступим по 10% экрана}
  42.   ScreenXstart := GetMaxX div 10;
  43.   ScreenXfinish := GetMaxX - ScreenXstart;
  44.   ScreenYstart := GetMaxY div 10;
  45.   ScreenYfinish := GetMaxY - ScreenYstart;
  46.   {расчёт масштабных коэффициентов}
  47.   ScaleX := (ScreenXfinish - ScreenXstart) / (Xfinish - Xstart);
  48.   ScaleY := (ScreenYfinish - ScreenYstart) / (Yfinish - Ystart);
  49.   {построение осей координат}
  50.   SetColor(7);
  51.   MoveTo(ScreenXstart, ScreenYstart);
  52.   LineTo(ScreenXstart, ScreenYfinish);
  53.   LineTo(ScreenXfinish, ScreenYfinish);
  54.   LineTo(ScreenXfinish, ScreenYstart);
  55.   LineTo(ScreenXstart, ScreenYstart);
  56.  
  57.   MoveTo((ScreenXfinish + ScreenXstart) div 2, ScreenYstart);
  58.   LineTo((ScreenXfinish + ScreenXstart) div 2, ScreenYfinish);
  59.   {построение 1-го графика}
  60.   SetColor(5);
  61.   IsNextVisiblePixel := False;
  62.   X  := Xstart;
  63.   dX := (Xfinish - Xstart) / 1000;
  64.   while X <= Xfinish do
  65.   begin
  66.     Y := f1(X);
  67.     Xscreen := round((X - Xstart) * ScaleX) + ScreenXstart;
  68.     Yscreen := -round((Y - Ystart) * ScaleY) + ScreenYfinish;
  69.     if (Xscreen >= ScreenXstart) and (Xscreen <= ScreenXfinish) and
  70.       (Yscreen > ScreenYstart) and (Yscreen < ScreenYfinish) then
  71.     begin
  72.       if IsNextVisiblePixel then
  73.         LineTo(Xscreen, Yscreen)
  74.       else
  75.         MoveTo(Xscreen, Yscreen);
  76.       IsNextVisiblePixel := True;
  77.     end
  78.     else
  79.       IsNextVisiblePixel := False;
  80.     X := X + dX;
  81.   end;
  82.   {построение 2-го графика}
  83.   SetColor(4);
  84.   IsNextVisiblePixel := False;
  85.   X  := Xstart;
  86.   dX := (Xfinish - Xstart) / 1000;
  87.   while X <= Xfinish do
  88.   begin
  89.     Y := f2(X);
  90.     Xscreen := round((X - Xstart) * ScaleX) + ScreenXstart;
  91.     Yscreen := -round((Y - Ystart) * ScaleY) + ScreenYfinish;
  92.     if (Xscreen >= ScreenXstart) and (Xscreen <= ScreenXfinish) and
  93.       (Yscreen > ScreenYstart) and (Yscreen < ScreenYfinish) then
  94.     begin
  95.       if IsNextVisiblePixel then
  96.         LineTo(Xscreen, Yscreen)
  97.       else
  98.         MoveTo(Xscreen, Yscreen);
  99.       IsNextVisiblePixel := True;
  100.     end
  101.     else
  102.       IsNextVisiblePixel := False;
  103.     X := X + dX;
  104.   end;
  105.   ReadKey;
  106. end.

Объяснение кода листинга программы

  1. В функции f1 коэффициент масштабирования 16 умножается на квадрат аргумента X.
  2. В функции f2 коэффициент масштабирования 1/7 умножается на квадрат аргумента X.
  3. Переменные GraphDevice, GraphMode инициализируются функцией Detect, которая возвращает детектированный устройство для графика.
  4. Переменные ScreenXstart, ScreenXfinish, ScreenYstart и ScreenYfinish вычисляются как 10% от максимальных значений X и Y.
  5. Коэффициенты масштабирования ScaleX и ScaleY вычисляются как отношение максимальных значений ScreenX и ScreenY к максимальным значениям X и Y.
  6. Оси координат строятся с помощью функции MoveTo и LineTo.
  7. Первый график строится с помощью функции f1.
  8. Второй график строится с помощью функции f2.
  9. Переменная IsNextVisiblePixel используется для отслеживания следующего видимого пикселя при построении графика.
  10. Переменные X, Y и dX используются для вычисления текущего положения X и Y и изменения их значения на единицу dX при каждом шаге построения графика.
  11. Переменные Xscreen и Yscreen используются для вычисления координат пикселей на экране для каждого шага построения графика.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

15   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы