Advertisement
CherMi

Lab 14

Dec 6th, 2019
244
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.36 KB | None | 0 0
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <errno.h>
  5. #include <stdlib.h>
  6. #include "graphics.h"
  7.  
  8. double f(double x); //Подпрограмма, вычисляющая значение функции x^2*exp(-x)
  9. void draw_chart(double a, double b, int x_steps, int y_steps); //Подпрограмма, рисующая график функции x^2*exp(-x)
  10. void draw_histogram(double a, double b, int x_steps, int y_steps); //Подпрограмма, рисующая гистограмму функции x^2*exp(-x)
  11. void save_chart(char* file_name); //Подпрограмма, рисующая и сохраняющая гистограмму функции x^2*exp(-x)
  12.  
  13. /*struct RGBQUAD
  14. {
  15.     unsigned char rgbBlue;
  16.     unsigned char rgbGreen;
  17.     unsigned char rgbRed;
  18.     unsigned char rgbReserved;
  19. };*/
  20.  
  21. /*struct BITMAPFILEHEADER
  22. {
  23.  
  24.     unsigned short int bfType;
  25.     unsigned long bfSize;
  26.     unsigned short int bfReserved1;
  27.     unsigned short int bfReserved2;
  28.     unsigned long bfOffBits;
  29. };*/
  30.  
  31. /*struct BITMAPINFOHEADER
  32. {
  33.     unsigned long biSize;
  34.     long biWidth;
  35.     long biHeight;
  36.     unsigned short int biPlanes;
  37.     unsigned short int biBitCount;
  38.     unsigned long biCompression;
  39.     unsigned long biSizeImage;
  40.     long biXPelsPerMeter;
  41.     long biYPelsPerMeter;
  42.     unsigned long biClrUsed;
  43.     unsigned long biClrImportant;
  44. };*/
  45.  
  46. RGBQUAD get_ega_color(int color);
  47. int main()
  48. {
  49.     int res;
  50.     double a = -1, b = 2;
  51.  
  52.     int gdriver = DETECT, gmode;
  53.     initgraph(&gdriver, &gmode, ""); //Инициализация графического режима
  54.     res = graphresult();
  55.     if (res != grOk)
  56.     {
  57.         printf("An error has occured while initializing graphicsl output.");
  58.         return -1;
  59.     }
  60.  
  61.     draw_chart(a, b, 78, 25);
  62.     draw_histogram(a, b, 60, 80);
  63.     save_chart("C:\\test\\out.bmp");
  64.     closegraph(); //Выход из графического режима
  65.     return 0;
  66. }
  67.  
  68. double f(double x) //Подпрограмма, вычисляющая значение функции x^2*exp(-x)
  69. {
  70.     double ctrl, result;
  71.     result = x * x;
  72.     if (fabs(ctrl = result / x - x) >= 0.00001)
  73.     {
  74.         //TODO: посмотреть, нужно ли errno
  75.         errno = ERANGE;
  76.         return -1;
  77.     }
  78.     return (result / exp(x));
  79. }
  80.  
  81. void draw_chart(double a, double b, int x_steps, int y_steps) //Подпрограмма, рисующая график функции x^2*exp(-x)
  82. {
  83.     int i, max_x, max_y, zero_x, zero_y;
  84.     double x, y;
  85.     double top_y, x_inc, del_x, del_y;
  86.     double len = b - a; //Длина отрезка
  87.     double offset_percent; //Процент от максимальных координат, который отступается от осей.
  88.  
  89.     max_x = getmaxx();
  90.     max_y = getmaxy();
  91.  
  92.     //Сделать фон белым, а цвет рисования чёрным.
  93.     setfillstyle(1, 15);
  94.     bar(0, 0, max_x, max_y);
  95.     setcolor(0);
  96.     setlinestyle(0, 0, 1);
  97.  
  98.     offset_percent = 0.1;
  99.  
  100.     //Вычисляем положение нуля на оси x
  101.     zero_x = max_x * offset_percent;
  102.     if (a < 0)
  103.     {
  104.         zero_x += (fabs(a)/len) * (max_x * (1 - 2 * offset_percent)); //TODO
  105.     }
  106.  
  107.     zero_y = max_y * (1 - offset_percent);
  108.  
  109.     line(max_x * offset_percent, zero_y, max_x * (1 - offset_percent), zero_y); //Ось x
  110.     del_x = (max_x * (1 - 2 * offset_percent)) / x_steps;
  111.     for (i = 0; i < x_steps; i++)
  112.     {
  113.         line(max_x * offset_percent + i * del_x, zero_y + 1, max_x * offset_percent + i * del_x, zero_y - 1);
  114.     }
  115.  
  116.     line(zero_x, zero_y, zero_x, max_y * offset_percent); //Ось y
  117.     del_y = (max_y * (1 - 2 * offset_percent)) / y_steps;
  118.     for (i = 0; i < y_steps; i++)
  119.     {
  120.         line(zero_x - 3, zero_y - del_y * i, zero_x + 3, zero_y - del_y * i);
  121.     }
  122.  
  123.     //TODO: добавить стрелки
  124.     //TODO: добавить деления
  125.     //TODO: добавить подписи
  126.  
  127.     offset_percent += 0.03;
  128.     del_x = (max_x * (1 - 2 * offset_percent)) / len; //Цена делания по оси x
  129.     x_inc = len / x_steps;
  130.  
  131.     top_y = (f(a) > f(b)) ?  f(a) : f (b); //Наибольшее значение по y. TODO: исправить
  132.     del_y = (zero_y - max_y * offset_percent) / top_y; //Цена деления по оси y;
  133.  
  134.     double prev_x, prev_y, cur_x, cur_y;
  135.     x = a;
  136.     prev_x = x * del_x + zero_x;
  137.     prev_y = zero_y - f(x) * del_y;
  138.     x += x_inc;
  139.     for (i = 1; i < x_steps; i++, x += x_inc)
  140.     {
  141.         cur_x = x * del_x + zero_x;
  142.         cur_y = zero_y - f(x) * del_y;
  143.         line(prev_x, prev_y, cur_x, cur_y);
  144.         prev_x = cur_x;
  145.         prev_y = cur_y;
  146.     }
  147.     system("pause");
  148. }
  149.  
  150. void draw_histogram(double a, double b, int x_steps, int y_steps)
  151. {
  152.     int i, max_x, max_y, zero_x, zero_y;
  153.     double x, y;
  154.     double top_y, x_inc, del_x, del_y;
  155.     double len = b - a; //Длина отрезка
  156.     double offset_percent; //Процент от максимальных координат, который отступается от осей.
  157.  
  158.     max_x = getmaxx();
  159.     max_y = getmaxy();
  160.  
  161.     //Сделать фон белым, а цвет рисования чёрным.
  162.     setfillstyle(1, 15);
  163.     bar(0, 0, max_x, max_y);
  164.     setcolor(0);
  165.     setlinestyle(0, 0, 1);
  166.  
  167.     offset_percent = 0.1;
  168.  
  169.     //Вычисляем положение нуля по вертикали (на оси y)
  170.     zero_x = max_y * offset_percent;
  171.     if (a < 0)
  172.     {
  173.         zero_x += (fabs(a) / len) * (max_y * (1 - 2 * offset_percent)); //TODO
  174.     }
  175.  
  176.     zero_y = max_x * offset_percent;
  177.     line(max_x * offset_percent, zero_x, max_x * (1 - offset_percent), zero_x); //Ось y (горизонтальная)
  178.     line(zero_y, max_y * offset_percent, zero_y, max_y *  (1 - offset_percent)); //Ось x (вертикальная)
  179.  
  180.     offset_percent += 0.03;
  181.     del_x = (max_y * (1 - 2 * offset_percent)) / len; //Цена деления по оси x (вертикальная)
  182.     x_inc = len / x_steps;
  183.  
  184.     top_y = (f(a) > f(b)) ? f(a) : f(b); //Наибольшее значение по y. TODO: исправить
  185.     del_y = (max_x * (1 - 2 * offset_percent)) / top_y; //Цена делания по оси y (горизонтальная)
  186.  
  187.  
  188.     double prev_x, prev_y, cur_x, cur_y;
  189.     char str[10];
  190.     setbkcolor(WHITE);
  191.     settextstyle(SMALL_FONT, HORIZ_DIR, 3);
  192.  
  193.     for (x = a, i = 0; i < x_steps; i++, x += x_inc)
  194.     {
  195.         cur_y = zero_y + f(x) * del_y;
  196.         cur_x = zero_x + x * del_x;
  197.         line(zero_y, cur_x, cur_y, cur_x);
  198.         sprintf(str, "%f", f(x));
  199.         outtextxy(cur_y + 10, cur_x - 3, str);
  200.         prev_x = cur_x;
  201.         prev_y = cur_y;
  202.     }
  203.  
  204.     system("pause");
  205.  
  206. }
  207.  
  208. RGBQUAD get_ega_color(int color) {
  209.  
  210.     RGBQUAD v;
  211.     v.rgbReserved = 0;
  212.  
  213.     switch (color) {
  214.     case BLACK: v.rgbRed = 0; v.rgbGreen = 0; v.rgbBlue = 0; break;
  215.     case BLUE: v.rgbRed = 0; v.rgbGreen = 0; v.rgbBlue = 128; break;
  216.     case GREEN: v.rgbRed = 0; v.rgbGreen = 128; v.rgbBlue = 0; break;
  217.     case CYAN: v.rgbRed = 0; v.rgbGreen = 128; v.rgbBlue = 128; break;
  218.     case RED: v.rgbRed = 128; v.rgbGreen = 0; v.rgbBlue = 0; break;
  219.     case MAGENTA: v.rgbRed = 128; v.rgbGreen = 0; v.rgbBlue = 128; break;
  220.     case BROWN: v.rgbRed = 128; v.rgbGreen = 64; v.rgbBlue = 0; break;
  221.     case LIGHTGRAY: v.rgbRed = 128; v.rgbGreen = 128; v.rgbBlue = 128; break;
  222.     case DARKGRAY: v.rgbRed = 64; v.rgbGreen = 64; v.rgbBlue = 64; break;
  223.     case LIGHTBLUE: v.rgbRed = 0; v.rgbGreen = 0; v.rgbBlue = 255; break;
  224.     case LIGHTGREEN: v.rgbRed = 0; v.rgbGreen = 255; v.rgbBlue = 0; break;
  225.     case LIGHTCYAN: v.rgbRed = 0; v.rgbGreen = 255; v.rgbBlue = 255; break;
  226.     case LIGHTRED: v.rgbRed = 255; v.rgbGreen = 0; v.rgbBlue = 0; break;
  227.     case LIGHTMAGENTA: v.rgbRed = 255; v.rgbGreen = 0; v.rgbBlue = 255; break;
  228.     case YELLOW: v.rgbRed = 255; v.rgbGreen = 255; v.rgbBlue = 0; break;
  229.     case WHITE: v.rgbRed = 255; v.rgbGreen = 255; v.rgbBlue = 255; break;
  230.     }
  231.     return v;
  232.  
  233. }
  234. void save_chart(char* file_name)
  235. {//Подпрограмма, рисующая и сохраняющая гистограмму функции x^2*exp(-x)
  236.     //int nWidth = getmaxx() + 1;
  237.     int nWidth = getmaxx();
  238.     //int nHeight = getmaxy() + 1;
  239.     int nHeight = getmaxy();
  240.     FILE *pFile = fopen(file_name, "wb");
  241.  
  242.     if (pFile == NULL)
  243.     {
  244.         printf("Could not open file");
  245.         return;
  246.     }
  247.     // save bitmap file header
  248.     BITMAPFILEHEADER fileHeader;
  249.     fileHeader.bfType = 0x4d42;
  250.     fileHeader.bfSize = 0;
  251.     fileHeader.bfReserved1 = 0;
  252.     fileHeader.bfReserved2 = 0;
  253.     fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 16 * sizeof(RGBQUAD);
  254.     fwrite((char*)&fileHeader, sizeof(fileHeader), 1, pFile);
  255.  
  256.     // save bitmap info header
  257.     BITMAPINFOHEADER infoHeader;
  258.     infoHeader.biSize = sizeof(infoHeader);
  259.     infoHeader.biWidth = nWidth;
  260.     infoHeader.biHeight = nHeight;
  261.     infoHeader.biPlanes = 1;
  262.     infoHeader.biBitCount = 4;
  263.     infoHeader.biCompression = 0; // BI_RGB
  264.     infoHeader.biSizeImage = 0;
  265.     infoHeader.biXPelsPerMeter = 0;
  266.     infoHeader.biYPelsPerMeter = 0;
  267.     infoHeader.biClrUsed = 16;
  268.     infoHeader.biClrImportant = 16;
  269.     fwrite((char*)&infoHeader, sizeof(infoHeader), 1, pFile);
  270.  
  271.     // palette output
  272.     RGBQUAD palette[16];
  273.     memset(&palette[0], 16 * sizeof(RGBQUAD), 0);
  274.     for (long clr = 0; clr < 16; clr++) {
  275.         palette[clr] = get_ega_color(clr);
  276.     }
  277.     fwrite((char*)(&palette), 1, 16 * sizeof(RGBQUAD), pFile);
  278.  
  279.     // raster output
  280.     int maxx = (getmaxx() + 1) / 2;
  281.     int maxy = (getmaxy() - 1); //TODO
  282.     for (int y = maxy; y >= 0; y--) {
  283.         for (int x = 0; x < maxx; x++) {
  284.  
  285.             // we will place 2 pixels into one byte
  286.             unsigned char pix1 = getpixel(x * 2, y);
  287.             unsigned char pix2 = getpixel(x * 2 + 1, y);
  288.             unsigned char temp = pix2 | (pix1 << 4);
  289.             fwrite(&temp, sizeof(temp), 1, pFile);
  290.         }
  291.     }
  292.     fclose(pFile);
  293. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement