На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Друзья, соблюдайте, пожалуйста, правила форума и данного раздела:
Данный раздел не предназначен для вопросов и обсуждений, он содержит FAQ-заготовки для разных языков программирования. Любой желающий может разместить здесь свою статью. Вопросы же задавайте в тематических разделах!
• Если ваша статья может быть перенесена в FAQ соответствующего раздела, при условии, что она будет оформлена в соответствии с Требованиями к оформлению статей.
• Чтобы остальным было проще понять, указывайте в описании темы (подзаголовке) название языка в [квадратных скобках]!
Модераторы: Модераторы
  
> Графика - Graphics , [Pascal]
    ===========================

    Это заготовка. Просто содрал с одного сайта, ну и немного добавил от себя.
    Будет наподобие уроков в одной теме. Зацените...
    ===========================

    - Графика - Graphics -


    Необходимые процедуры и функции для работы с графикой собраны стандартном модуле - Graph.
    Инициализация графики производится с помощью процедуры InitGraph, которая имеет вид:

    InitGraph(GraphDriver, GraphMode, Path);

    где переменные GraphDriver и GraphMode имеют тип Integer, а переменная Path имеет тип String.

    GraphDriver - целая переменная, определяющая тип графического драйвера (VGA,EGA,CGA,..)
    Большинство мониторов имеют тип VGA, и выше - SVGA(Super VGA),XGA...

    GraphMode задает режим работы графического адаптера.
    Для VGA это режимы VGALo,VGAMed и VGAHi.

    Допустим, программа находится в директории C:\TP7\MYPROG
    Path - путь к файлу-драйверу egavga.bgi
    Если он находится в той же директории, что и наша программа, то укажем Path=''
    Как правило, файл egavga.bgi находится в директории BGI, поэтому Path='..\BGI'
    В случае, если вы запускаете программу, неправильно указав путь к этому файлу,
    получите сообщение-ошибку о том, что графический режим не инициализирован.

    Чтобы автоматически определить тип графического драйвера, существует функция Detect, которая применяется так:
    GraphDriver:=Detect;

    Процедура CloseGraph заканчивает работу с графикой и переводит экран обратно в текстовый режим.

    Для работы с графикой нам надо дописать в разделе Uses модуль Graph.

    Пример.
    ExpandedWrap disabled
      Uses
          Graph;{Подключение модуля библиотеки графических процедур}
       
      Var
          GraphDriver,
          GraphMode : integer;
       
      Begin
          GraphDriver := detect; {автоопределение типа драйвера }
       
          {Инициализация графического режима}
          InitGraph(GraphDriver, GraphMode, '..\BGI');
       
          if GraphResult<>grOK { графический режим не установился }
             then halt; { прерываем программу }
       
          { Сюда мы будем добавлять процедуры рисования.
            В следующем примере... }
       
          Writeln('Press Enter');
          readln; { нажать Ввод }
       
          СloseGraph; {Закрытие графического режима}
      End.


    Система координат в графическом режиме.
    Все пиксели считаются относительно левого верхнего угла экрана с координатами (0,0)
    user posted image
    Чтобы узнать максимальные координаты экрана в текущем режиме работы, воспользуемся стандартными функциями GetMaxX и GetMaxY.
    Итак, отсчет начинается с верхнего левого угла с координатами (0;0), значение Х - столбец, отсчет слева направо; значение Y - строка, отсчет сверху вниз.

    Чтобы строить изображение, нужно указать точку начала вывода. В графическом режиме нет видимого курсора, но есть так называемый невидимый текущий указатель (Current Pointer). После инициализации графического режима указатель стоит в точке (0;0). Чтобы переместить его в нужное место используют следующие процедуры:

    MoveTo (X, Y), где переменные X, Y типа Integer - перемещает текущий указатель в точку с координатами (X,Y).

    Например, MoveTo (200, 100)

    MoveRel (dX, dY), где переменные dX, dY типа Integer - перемещает текущий указатель по горизонтали на расстояние, равное dX пикселям, а по вертикали на расстояние, равное dY пикселям. (Relative (англ.) - относительно)

    Например, если после выполнения предыдущей процедуры текущий указатель находится в точке (200, 100), то после выполнения процедуры MoveRel (25, 150) он будет находится в точке с координатами (225, 250).

    Эта тема была разделена из темы "Неотёсанные топики"
    Сообщение отредактировано: Jin X -
      Пример применения GetImage и PutImage для анимации.

      Принцип анимации:
      1. сначала, когда экран очищен, нужно нарисовать объект, который будем анимировать (для примера я взял курсор).
      2. очищаем экран процедурой ClearDevice и выводим курсор в нужное место
      3. стираем предыдущее изображение (старые координаты)
      4. после того, как координаты курсора изменились, сохраняем изображение и отрисовываем снова курсор
      5. для повторения анимации повторять пункты 3 и 4.

      ExpandedWrap disabled
        program GrCursor;
        uses CRT, Graph;
         
        procedure InitGraphics;
        Var grDriver, grMode : Integer;
        begin
             grDriver := Detect;
             InitGraph (grDriver, grMode, '..\bgi');
             if GraphResult<>grOk then
             begin
                  writeln ('Gr. Error!');
                  halt (1);
             end;
        end;
         
        Const
          Width  = 20;
          Height = 20;
          Step   = 20;
         
        var c: char;
            size,x,y,i: word;
            PCursor, PScreenBlock: pointer;
            cx, cy: integer;
         
        procedure MoveCursor (dx, dy: integer);
        begin
             PutImage (X, Y, PScreenBlock^, NormalPut);  { восстановить предыдущий блок }
             { изменить координаты }
             inc (X, dx);
             inc (Y, dy);
             GetImage (X, Y, X+Width, Y+Height, PScreenBlock^); { сохранить текущий блок перед тем, как отрисовывать курсор }
             PutImage (X, Y, PCursor^, OrPut); { вставить новый блок }
        end;
         
        begin
             InitGraphics;
         
             if GraphResult <> grOk then
                exit;
         
             cx := GetMaxX div 2;
             cy := GetMaxY div 2;
         
             x := cx - Width div 2;
             y := cy - Height div 2;
         
             SetColor (LightBlue);
             Line (0, 0, Width, Height);
             Line (0, Height, Width, 0);
         
             Size := ImageSize (0, 0, Width, Height); { Вычисляем размер картинки, который будем резервировать }
             GetMem (PCursor, Size);   { Резервируем память для курсора }
             GetMem (PScreenBlock, Size);   { Резервируем память сохраняемого блока }
             GetImage (0, 0, Width, Height, PCursor^); { Сохранить курсор в память }
         
             ClearDevice;
             MoveCursor (0, 20);
             SetColor (Red);
             Line (0, 0, GetMaxX, GetMaxY);
         
             repeat
                   c := readkey;
                   if c=#0 then
                      c := readkey;
         
                   case c of
                   #72: {Up}
                    MoveCursor (0, -Step);
         
                   #80: {Down}
                    MoveCursor (0, Step);
         
                   #75: {Left}
                    MoveCursor (-Step, 0);
         
                   #77: {Right}
                    MoveCursor (Step, 0);
                   end;
             until c=#27;
             { Освобождение памяти }
             FreeMem (PCursor, Size);
             FreeMem (PScreenBlock, Size);
             CloseGraph;
        end.


      Зацените. Что добавить или заменить?
      П.С. А это кому-то надо вообще?

      Добавлено
      Да, кстати:
      Процедура MoveCursor собственно, и выполняет анимацию. Передаваемые в неё параметры - это смещение dx,dy от предыдущего значения (x,y), то есть курсор переместится в точку (x+dx,y+dy).
      Step - шаг передвижения.

      Не забывайте, что точка отсчёта (0,0) находится в левом верхнем углу, и направление оси Y - вниз, а не вверх, как мы привыкли.

      Добавлено
      Желательно добавить проверку выхода курсора за границы экрана, но вы можете сделать это сами.

      Это сообщение было перенесено сюда или объединено из темы "Создаём Offline FAQ"
        Цитата Romtek @
        Кто может составить статью по применению видеостраниц для анимации? Описать всё популярным языком.

        дык там три строчки
        ExpandedWrap disabled
          var page:byte;
          ...
          while not (exit_event) do begin
            page:=1-page; {страницы нумеруются с нуля, этим оператором меняется 0 на 1, а 1 на 0}
            setactivepage(page); {теперь все рисование будет на спрятанной странице}
            process_required_events; {реагируем на кнопочки итп}
            draw_entire_page; {перерисовываем}
            setvisualpage(page); {показываем только что нарисованную страницу}
            time_wait; {обычно delay или работа с таймером, в это время созерцаем нарисованное}
          end;


        Это сообщение было перенесено сюда или объединено из темы "Создаём Offline FAQ"
          ExpandedWrap disabled
            {
              Rectangle rotation around the first point
              (c) Romtek, 2005
            }
             
            {$G+,N+,E-}
            uses Graph, CRT;
             
            const
                N = 4; {vertices number}
             
            type
                TPoint = record {structure, that stores point coordinate}
                 x, y: integer;
                end;
                TPoly = array [1..N] of TPoint; {all coordinates}
             
            var
              Rect: TPoly;
              x0, y0: integer;
             
            procedure InitGr;
            var
               gd, gm: integer;
            begin
                 gd := VGA;
                 gm := VGAHi;
                 InitGraph (gd, gm, '..\bgi'); {Check if BGI driver is in the path}
                 if GraphResult <> grOk then
                    halt (1);
            end;
             
            procedure PlotRect;
            var
               i: integer;
            begin
                 MoveTo (x0 + Rect[1].x, y0 - Rect[1].y);
             
                 for i := 2 to N do
                 with Rect[i] do
                     LineTo (x0 + x, y0 - y);
             
                 LineTo (x0 + Rect[1].x, y0 - Rect[1].y);
            end;
             
            procedure Rotate (phi: single);
            var
               xx, yy,
               i: integer;
            begin
                 for i := 2 to N do
                 with Rect[i] do
                 begin
                      xx := x;
                      yy := y;
                      x := Rect[1].x + Round ((xx-Rect[1].x) * cos(Phi) - (yy-Rect[1].y) * sin(Phi));
                      y := Rect[1].y + Round ((xx-Rect[1].x) * sin(Phi) + (yy-Rect[1].y) * cos(Phi));
                 end;
            end;
             
            var
               i: integer;
             
            begin
                 Randomize;
                 InitGr;
                 x0 := GetMaxX div 2;
                 y0 := GetMaxY div 2;
             
                 for i := 1 to N do
                 with Rect[i] do
                 begin
                      x := Random (x0) - (x0 div 2);
                      y := Random (y0) - (y0 div 2);
                 end;
             
                 SetColor (Yellow);
             
                 SetWriteMode(XORPut);
                 {From help: Two successive XOR commands will erase the
                 line and restore the screen to its original appearance.}
             
                 PlotRect;
                 readln;
             
                 while not KeyPressed do
                 begin
                      PlotRect; {Erase old rectangle}
                      Rotate (pi/6.0); {30 degrees}
                      PlotRect; {Put new rectangle}
                      delay (800);
                 end;
             
                 CloseGraph;
            end.


          Добавлено
          ExpandedWrap disabled
            {
              Управление движением курсора с помощью стрелок
              (c)  Vesper, Romtek
            }
             
            uses Graph, Crt;
             
            procedure InitGraphics;
            Const
               PathToBGI = 'e:\bp\bgi';
            var
               gd, gm,
               ErrorCode: Integer;
             
            begin
              gd := VGA;
              gm := VGAHi;
              InitGraph (gd, gm, PathToBGI);
              ErrorCode := GraphResult;
              if ErrorCode <> grOk then
              begin
                   Writeln ('Graphics error: ', GraphErrorMsg (ErrorCode));
                   Readln;
                   Halt (1);
              end;
            end;
             
            Const
               Border = 5;
             
            var
               i, x, y,
               mx, my :integer;
               eexit:byte;
               c:char;
             
            procedure DrawCursor;
            begin
              line (x - 15, y, x - 1, y);
              line (x, y - 15, x, y - 1);
              line (x + 15, y, x + 1, y);
              line (x, y + 15, x, y + 1);
            end;
             
            begin
              eexit := 0;
             
              InitGraphics;
              mx := GetMaxX;
              my := GetMaxY;
              x := mx div 2;
              y := my div 2;
             
              OutText ('Press Esc to exit');
              setcolor (Yellow);
              DrawCursor;
              repeat
                c := readkey;
                if c=#27 then eexit := 1;
                if c=#0 then
                begin
                  c := readkey;
                  setcolor (Black);
                  DrawCursor;
                  case c of
                  'K':
                  begin
                       dec (x, 5);
                       if x <= Border then
                          x := Border;
                  end;
             
                  'M':
                  begin
                       inc (x, 5);
                       if x >= mx - Border then
                          x := mx - Border;
                  end;
             
                  'H':
                  begin
                       dec (y, 5);
                       if y <= Border then
                          y := Border;
                  end;
             
                  'P':
                  begin
                       inc (y, 5);
                       if y >= my - Border then
                          y := my - Border;
                  end;
                  end;
             
                  setcolor (Yellow);
                  DrawCursor;
                end;
              until eexit > 0;
              closegraph;
            end.
          Сообщение отредактировано: Romtek -
            Пример построения графика распределения случайных чисел (Random) с применением всех правил масштабирования.

            Рассмотрим такое задание:
              Нарисовать график нормального распределения случайных чисел.


            Для этого определим сначала границы вывода графика в рамке, у которой отступ по горизонтали составляет
            XMargin процентов от общей ширины экрана (пикселей) и отступ по вертикали YMargin процентов.
            ExpandedWrap disabled
                XMargin     = 4;  { % ширины экрана }
                YMargin     = 20; { % высоты экрана }

            ExpandedWrap disabled
              ---------------
              | ----------- |
              | |         | |
              | |         | |
              | |         | |
              | ----------- |
              ---------------

            Xborder и Yborder - это количество пикселей между границей экрана и рамкой по горизонтали и вертикали,
            соответственно. Их вычисляем так:
            ExpandedWrap disabled
                   Xborder := GetMaxX div 100 * Xmargin;
                   Yborder := GetMaxY div 100 * Ymargin;

            Xmin, Xmax - левая и правая границы рамки,
            Ymin, Ymax - верхняя и нижняя границы рамки.
            Эти параметры надо вычислить, исходя из данных Xborder и Yborder.

            Допустим, имеем такие параметры нормального распределения:
            ExpandedWrap disabled
                MeanValue : single = 0.0; { мат.ожидание }
                StDev     : single = 1.2; { среднеквадр.отклонение }


            Теперь надо задать диапазон значений по оси X и оси Y.
            По оси X мы ничем не ограничены, так как нет зависимости от х (генератор случайных чисел не имеет
            входного параметра), поэтому берём Xmin, Xmax.
            По оси Y надо задать нижнюю и верхнюю границу YminValue и YmaxValue, которые принимают максимальные
            значения генератора + оставить некоторый запас, чтобы график не выходил за пределы рамки:
            ExpandedWrap disabled
                YmaxValue : single = 5.0;
                YminValue : single = -5.0;


            Начальное значение x будет Xmin, а конечное - Xmax. Разобьём этот промежуток на Parts частей:
            ExpandedWrap disabled
                Parts = 8;

            Шаг между соседними значениями вычисляется тогда по формуле
            ExpandedWrap disabled
               Xstep = Width / Parts


            Чтобы вывести график в пределах заданной границы рамки, нужно вычислить масштаб по горизонтали.
            Т.е. поделить высоту экрана на ширину диапазона принимаемых значений:
            ExpandedWrap disabled
               Yscale = Height / (YmaxValue - YminValue)


            Введём точку отсчёта (Xorig , Yorig) ,относительно которой будет строиться график распределения.
            Тогда сгенерированное случайное число получает координаты (xs , ys)
            ExpandedWrap disabled
              xs = Xorig + x
              ys = Yorig - NormRand (MeanValue, StDev) * Yscale

            Функция NormRand генерирует случайное число по закону нормального распределения с заданными параметрами
            MeanValue и StDev.

            К значению x прибавляем каждый раз шаг Xstep и таким образом рисуем график.

            ExpandedWrap disabled
              (*
                Data visualization of Normal distribution.
                (c) 2005, Romtek
              *)
               
              {$N+}
              program Viz2;
              Uses Crt, Graph {, v256 , PCX16{};
               
              Const
                Title       = 'Data visualization of Normal distribution';
                TitleColor  = White;
                BorderColor = Cyan;
                MeanColor   = Red;
                StDevColor  = LightGray;
                LineColor   = Magenta;
                NumColor    = Yellow;
               
                XMargin     = 4;  { % ширины экрана }
                YMargin     = 20; { % высоты экрана }
               
                MeanValue : single = 0.0; { мат.ожидание }
                StDev     : single = 1.2; { среднеквадр.отклонение }
                YmaxValue : single = 5.0;
                YminValue : single = -5.0;
                Parts              = 8;
               
               
              { Распределение по нормальному закону }
              function NormRand (Mx, S : single) : single;
                { Mx - мат.ожидание, S - среднеквадр.отклонение }
              var
                A,B,R,SQ : single;
              begin
                repeat
                  A := 2.0 * Random - 1.0;
                  B := 2.0 * Random - 1.0;
                  R := Sqr(A) + Sqr(B)
                until (R < 1.0);
                SQ := Sqrt(-2.0 * Ln(R) / R);
                NormRand := Mx + S * A * SQ
              end;
               
              function f2s (f: single): String;
                { convert type single to string }
              var
                S: string[6];
              begin
                Str(f : 3 : 2, S);
                f2S := S;
              end;
               
              procedure PlotGraph;
              var
                Xorig, Yorig,
                x, Xstep,
                Xmin, Xmax,
                Ymin, Ymax,
                Width, Height,
                Xborder, Yborder,
                xs, ys         : integer;
                f, Yscale      : single;
               
              procedure Init;
                { расчёт всех данных }
              begin
                   Xborder := GetMaxX div 100 * Xmargin;
                   Yborder := GetMaxY div 100 * Ymargin;
                   Xmin := Xborder;
                   Ymin := Yborder;
                   Xmax := GetMaxX - Xborder;
                   Ymax := GetMaxY - Yborder;
               
                   { определение начала координат графика }
                  Xorig := Xmin;
                  Yorig := GetMaxY div 2;
               
                  { определение высоты и ширины графика }
                  Width := Xmax - Xmin;
                  Height := Ymax - Ymin;
               
                  { шаг между соседними значениями}
                  Xstep := Width div Parts;
               
                   Yscale := Height / (YmaxValue - YminValue);
              end;
               
              begin
                   Init;
               
                   { Вывести сообщение над графиком, по центру }
                   SetColor (TitleColor);
                   OutTextXY (
                    (GetMaxX - TextWidth (Title)) div 2,
                    (Ymin - TextHeight (Title)) div 2,
                    Title);
               
                  { граница поля графика }
                   SetColor (BorderColor);
                   Rectangle (Xmin, Ymin, Xmax, Ymax);
               
                  { Линия мат. ожидания }
                   SetColor (MeanColor);
                   ys:= Yorig - round (MeanValue * Yscale);
                   Line (Xmin, ys, Xmax, ys);
               
                  { Линии станд. отклонения }
                   SetColor (StDevColor);
                   SetLineStyle(DottedLn, 0, NormWidth);
                   ys := Yorig - round ((MeanValue - StDev) * Yscale);
                   Line (Xmin, ys, Xmax, ys);
                   ys := Yorig - round ((MeanValue + StDev) * Yscale);
                   Line (Xmin, ys, Xmax, ys);
               
                    { сам график }
                   SetLineStyle(SolidLn, 0, NormWidth);
                   x := 0;
                   while x <= (Xmax - Xmin) do
                  begin
                        SetColor (LineColor);
               
                    xs := Xorig + x;
                        f := NormRand (MeanValue, StDev);
                    ys := Yorig - round (f * Yscale);
               
                        if x = 0 then
                           MoveTo (xs, ys); { для первой точки установим графический курсор }
                        LineTo (xs, ys); { и будем рисовать линию от него до заданной точки.
                    После каждого вызова этой функции гр. курсор поменяет позицию на указанную в параметрах }
               
                        SetColor (NumColor);
                        OutTextXY (xs, ys, f2s (f)); { выводим значения случайных чисел }
               
                        x := x + Xstep; { прибавляем каждый раз шаг Xstep }
                  end;
              end;
               
              var
                Gd,Gm: Integer;
               
              begin
                Gd := Vga;
                gm := VgaHi;
                InitGraph(Gd,Gm,'..\..\bgi');
              {  SetVMode (v640x400);}
                if GraphResult <> grOk then
                   Halt (1);
               
                Randomize;
                PlotGraph;
               
                readLn;
              {  Save_PCX16('viz2.pcx');{}
                CloseGraph;
              end.


            График нормального распределения (скриншот):
            Прикреплённая картинка
            Прикреплённая картинка
              Зацените, плиз.
              Хочу услышать комментарии к этой программе.
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0549 ]   [ 16 queries used ]   [ Generated: 28.03.24, 20:06 GMT ]