allekco

comp

Dec 5th, 2019
200
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "StdAfx.h"
  2. #include "GF.h"
  3. #include <iostream>
  4. #include <vector>
  5.  
  6. using namespace std;
  7.  
  8. #ifndef M_PI
  9. const double M_PI = 3.1415926535897932384626433832795;
  10. #endif
  11.  
  12. enum { LEFT, RIGHT, BEYOND, BEHIND, ORIGIN, DEST, BETWEEN, COLLINEAR, PARALLEL, CROSS, SKEW, SKEW_CROSS,
  13.     SKEW_NO_CROSS, CROSS_LEFT, CROSS_RIGHT, INESSNTIAL, TOUCHING, COMPLEX, SIMPLE, CONVEX, NON_CONVEX,
  14.     INSIDE, OUTSIDE, CLOCKWISE, COUNTERCLOCKWISE };
  15.  
  16.  
  17. // Ваша реализация необходимых вам функций
  18. void DrawLine( int x0, int y0, int x1, int y1, RGBPIXEL color )
  19. {
  20.     int dx = abs(x1 - x0);      //
  21.     int dy = abs(y1 - y0);
  22.     int signX = x1 > x0 ? 1 : -1;       //if x1>x0 -> 1
  23.     int signY = y1 > y0 ? 1 : -1;
  24.     if (dx == 0 && dy == 0)
  25.     {
  26.         gfSetPixel(x0, y0, color);      //ставит один пиксель
  27.     }
  28.     else
  29.     {
  30.         if (dx - dy >= 0)       //прямоульгольник вытянут по x
  31.         {
  32.             int x = x0;
  33.             int y = y0;
  34.             int E = 2 * dy - dx;        //ошибка
  35.             while (x != x1 || y != y1)      //пока не дойдем в кон точку
  36.             {
  37.                 gfSetPixel(x, y, color);
  38.                 if (signY >= 0)     //усл для того чтобы одинаково от x0 и обратно
  39.                 {
  40.                     if (E >= 0)     //всегда измен x, иногда измен y
  41.                     {
  42.                         E -= 2 * dx;
  43.                         y += signY;    
  44.                     }
  45.                 }
  46.                 else
  47.                 {
  48.                     if (E > 0)
  49.                     {
  50.                         E -= 2 * dx;
  51.                         y += signY;
  52.                     }
  53.                 }
  54.                 x += signX;     //увеличиваем или умен на шаг в 1 пиксель
  55.                 E += 2 * dy;
  56.  
  57.             }
  58.             gfSetPixel(x, y, color);
  59.         }
  60.         else        //прям вытянут по y
  61.         {
  62.             int x = x0;
  63.             int y = y0;
  64.             int E = 2 * dx - dy;
  65.             while (x != x1 || y != y1)
  66.             {
  67.                 gfSetPixel(x, y, color);
  68.                 if (signX >= 0)
  69.                 {
  70.                     if (E >= 0)
  71.                     {
  72.                         E -= 2 * dy;
  73.                         x += signX;
  74.                     }
  75.                 }
  76.                 else
  77.                 {
  78.                     if (E > 0)
  79.                     {
  80.                         E -= 2 * dy;
  81.                         x += signX;
  82.                     }
  83.                 }
  84.                 y += signY;
  85.                 E += 2 * dx;
  86.             }
  87.             gfSetPixel(x, y, color);
  88.         }
  89.     }
  90.    
  91. }
  92.  
  93.  
  94.  
  95. void DrawPolygon(vector<vector<int>>& P, RGBPIXEL color)        // рисуем полигон. в динамический массиве 2 x n сначала x,потом y
  96. {
  97.     if (P.size() == 2)      //проверка что два столбика
  98.     {
  99.         if (P[0].size() == P[1].size())     //количество x должно совпадать с y
  100.         {
  101.             for (int i = 0; i < P[0].size() - 1; i++)      
  102.             {
  103.                 DrawLine(P[0][i], P[1][i], P[0][i + 1], P[1][i + 1], color);
  104.             }
  105.             DrawLine(P[0][P[0].size() - 1], P[1][P[0].size() - 1], P[0][0], P[1][0], color);        //прорисовываем отдельно последнюю строчку
  106.         }
  107.         else
  108.         {
  109.             cout << "Неправильно задан вектор" << endl;
  110.         }
  111.     }
  112.     else
  113.     {
  114.         cout << "Неправильно задан вектор" << endl;
  115.     }
  116. }
  117.  
  118.  
  119. int Classify(int x1, int y1, int x2, int y2, int x, int y)      //где лежит точка относительно прямой
  120. {
  121.     int ax = x2 - x1;       //вектор a=(ax,ay) совпадает с прямой
  122.     int bx = x - x1;
  123.     int ay = y2 - y1;
  124.     int by = y - y1;
  125.     int s = ax * by - bx * ay;
  126.     if (s > 0)
  127.         return LEFT;
  128.     if (s < 0)
  129.         return RIGHT;
  130.     if ((ax * bx < 0) || (ay * by < 0))     //на прямой продолжающей отрезок сзади
  131.         return BEHIND;
  132.     if ((ax * ax + ay * ay) < (bx * bx + by * by)) // спереди
  133.         return BEYOND;
  134.     if ((x == x1) && (y == y1)) //в начало попали
  135.         return ORIGIN;
  136.     if ((x == x2) && (y == y2))
  137.         return DEST;
  138.     return BETWEEN; // попали четко на отрезок
  139. }
  140.  
  141.  
  142. int PolyTypeConv(vector<vector<int>>& P)
  143. {
  144.     if (P[0].size() <= 2)       //чтобы было 3 x,y
  145.     {
  146.         gfDrawText(300, 300, "Not polygon", RGBPIXEL::Cyan());
  147.         return -1;
  148.     }
  149.     int type0 = Classify(P[0][0], P[1][0], P[0][1], P[1][1], P[0][2], P[1][2]); //запоминаем тип одной точку
  150.     for (int j = 0; j < P[0].size() - 1; j++)  //пробегаем по всем ребрам
  151.         for (int i = j + 2; i < P[0].size() + j - 1; i++)       //пробегаем по точкам, кроме ребра
  152.         {
  153.             int type = Classify(P[0][j], P[1][j], P[0][j + 1], P[1][j + 1], P[0][i % P[0].size()], P[1][i % P[0].size()]);
  154.             if (type == DEST || type == ORIGIN || type == BEYOND || type == BEHIND)
  155.             {
  156.                 gfDrawText(300, 300, "Not polygon", RGBPIXEL::Cyan());
  157.                 return -1;
  158.             }
  159.             if (type != type0) {
  160.             gfDrawText(200, 200, "Невыпуклый", RGBPIXEL(0, 128, 255));
  161.             return NON_CONVEX;      //невыпуклый полигон
  162.             }
  163.         }
  164.     gfDrawText(200, 200, "Выпуклый", RGBPIXEL(0, 128, 255));
  165.     return CONVEX;
  166. }
  167.  
  168. int Intersect(int xa, int ya, int xb, int yb, int xc, int yc, int xd, int yd, double& t)    //пересекаются 2 прямые ab и cd или нет
  169. {
  170.     int nx = yd - yc;       //направляющий вектор
  171.     int ny = xc - xd;
  172.     int denom = nx * (xb - xa) + ny * (yb - ya);        //знаменатель
  173.     if (denom == 0)
  174.     {
  175.         int type = Classify(xc, yc, xd, yd, xa, ya);
  176.         if ((type == LEFT) || (type == RIGHT))
  177.             return PARALLEL;
  178.         else
  179.             return COLLINEAR;       //на одной прямой
  180.     }
  181.     int num = nx * (xa - xc) + ny * (ya - yc);
  182.     t = -double(num) / double(denom);       //именно для отрезков пересечение
  183.     return CROSS;
  184. }
  185.  
  186.  
  187. int PolyTypeSimp(vector<vector<int>>& P)
  188. {
  189.     if (PolyTypeConv(P) == -1)
  190.     {
  191.         gfDrawText(300, 300, "Not polygon", RGBPIXEL::Cyan());
  192.         return -1;
  193.     }
  194.     if (PolyTypeConv(P) == CONVEX) {
  195.         gfDrawText(200, 100, "Простой", RGBPIXEL(0, 128, 255));
  196.         return SIMPLE;
  197.     }
  198.  
  199.     for (int j = 0; j < P[0].size() - 1; j++)
  200.         for (int i = j + 2; i < j + P[0].size() - 1; i++)
  201.         {
  202.             double t1 = -1;
  203.             double t2 = -2;
  204.             int type1 = Intersect(P[0][j], P[1][j], P[0][j + 1], P[1][j + 1], P[0][(i % P[0].size())], P[1][(i % P[0].size())], P[0][((i + 1) % P[0].size())], P[1][((i + 1) % P[0].size())], t1);
  205.             int type2 = Intersect(P[0][(i % P[0].size())], P[1][(i % P[0].size())], P[0][((i + 1) % P[0].size())], P[1][((i + 1) % P[0].size())], P[0][j], P[1][j], P[0][j + 1], P[1][j + 1], t2);
  206.             if (type1 == CROSS && type2 == CROSS)
  207.                 if (t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1) { //если обе t находятся от 0 до 1
  208.                     gfDrawText(200, 100, "Сложный", RGBPIXEL(0, 128, 255));
  209.                     return COMPLEX;     //сложный
  210.                 }
  211.         }
  212.     gfDrawText(200, 100, "Простой", RGBPIXEL(0, 128, 255));
  213.     return SIMPLE;
  214. }
  215.  
  216.  
  217. int EdgeType(int x0, int y0, int x1, int y1, int x, int y)      //каким образом прямая из точки x,y пересекает прямую
  218. {
  219.     switch (Classify(x0, y0, x1, y1, x, y))
  220.     {
  221.     case LEFT:
  222.         if (y > y0 && y <= y1)
  223.             return CROSS_LEFT;
  224.         else
  225.             return INESSNTIAL;  // не пересекает
  226.     case RIGHT:
  227.         if (y > y1 && y <= y0)
  228.             return CROSS_RIGHT;
  229.         else
  230.             return INESSNTIAL;
  231.     case BETWEEN:
  232.     case ORIGIN:
  233.     case DEST:
  234.         return TOUCHING;
  235.     default:
  236.         return INESSNTIAL;
  237.     }
  238. }
  239.  
  240.  
  241. int PInPolyEO(int x, int y, vector<vector<int>>& P)     //(лек) even-odd(считает число пересевчений, направл не интересует) закрашивает тольок ушки звезды
  242. {
  243.     int prm = 0;
  244.     for (int i = 0; i < P[0].size(); i++)
  245.     {
  246.         switch (EdgeType(P[0][i], P[1][i], P[0][(i + 1) % P[0].size()], P[1][(i + 1) % P[0].size()], x, y))
  247.         {
  248.         case TOUCHING:
  249.             return INSIDE;
  250.         case CROSS_LEFT:
  251.         case CROSS_RIGHT:
  252.             prm = 1 - prm;
  253.             break;
  254.         }
  255.     }
  256.     if (prm == 0)
  257.         return OUTSIDE;
  258.     else
  259.         return INSIDE;
  260. }
  261.  
  262.  
  263. int PInPolyNZW(int x, int y, vector<vector<int>>& P) //(лек) закрасит всю звезду (учитывает и направления тоже)
  264. {
  265.     int prm = 0;
  266.     for (int i = 0; i < P[0].size(); i++)
  267.     {
  268.         switch (EdgeType(P[0][i], P[1][i], P[0][(i + 1) % P[0].size()], P[1][(i + 1) % P[0].size()], x, y))
  269.         {
  270.         case TOUCHING:
  271.             return INSIDE;
  272.         case CROSS_LEFT:
  273.             prm = prm + 1;
  274.             break;
  275.         case CROSS_RIGHT:
  276.             prm = prm - 1;
  277.             break;
  278.         }
  279.     }
  280.     if (prm != 0)
  281.         return INSIDE;
  282.     else
  283.         return OUTSIDE;
  284. }
  285.  
  286.  
  287. int Max_El_1D(vector<int>& P) //максимальный элемент одномерного массива
  288. {
  289.     int max = P[0];
  290.     for (int i = 0; i < P.size(); i++)
  291.     {
  292.         if (P[i] > max)
  293.             max = P[i];
  294.     }
  295.     return max;
  296. }
  297.  
  298. int Min_El_1D(vector<int>& P)
  299. {
  300.     int min = P[0];
  301.     for (int i = 0; i < P.size(); i++)
  302.     {
  303.         if (P[i] < min)
  304.             min = P[i];
  305.     }
  306.     return min;
  307. }
  308.  
  309.  
  310. void FillingEO(vector<vector<int>>& P, RGBPIXEL color)
  311. {
  312.     int x_max = Max_El_1D(P[0]);
  313.     int x_min = Min_El_1D(P[0]);
  314.     int y_max = Max_El_1D(P[1]);
  315.     int y_min = Min_El_1D(P[1]);
  316.     for (int y = y_min; y <= y_max; y++) //увеличиваем по пикселю и закрашиваем если внутри
  317.         for (int x = x_min; x <= x_max; x++)
  318.         {
  319.             if (PInPolyEO(x, y, P) == INSIDE)
  320.                 gfSetPixel(x, y, color);
  321.         }
  322. }
  323.  
  324.  
  325. void FillingNZW(vector<vector<int>>& P, RGBPIXEL color)
  326. {
  327.     int x_max = Max_El_1D(P[0]);
  328.     int x_min = Min_El_1D(P[0]);
  329.     int y_max = Max_El_1D(P[1]);
  330.     int y_min = Min_El_1D(P[1]);
  331.     for (int y = y_min; y <= y_max; y++)
  332.         for (int x = x_min; x <= x_max; x++)
  333.         {
  334.             if (PInPolyNZW(x, y, P) == INSIDE)
  335.                 gfSetPixel(x, y, color);
  336.         }
  337. }
  338.  
  339.  
  340.  
  341.  
  342. //2 ЛР
  343.  
  344. vector<int> R3(double t, vector<vector<int>>& P) //(лек) параметрическое задание кривой безье 3 порядка
  345. {
  346.     vector<int> R = { 0 , 0 }; //точка
  347.     R[0] = int((1 - t) * (1 - t) * (1 - t) * P[0][0] + 3 * t * (1 - t) * (1 - t) * P[0][1] + 3 * t * t * (1 - t) * P[0][2] + t * t * t * P[0][3]);
  348.     R[1] = int((1 - t) * (1 - t) * (1 - t) * P[1][0] + 3 * t * (1 - t) * (1 - t) * P[1][1] + 3 * t * t * (1 - t) * P[1][2] + t * t * t * P[1][3]);
  349.     return R;
  350. }
  351.  
  352. int dist(int x, int y)  //(лек)
  353. {
  354.     return abs(x) + abs(y);
  355. }
  356.  
  357. void DrawBesie3(vector<vector<int>>& P, RGBPIXEL color) //(лек)
  358. {
  359.     int D = Max(dist(P[0][0] - 2 * P[0][1] + P[0][2], P[1][0] - 2 * P[1][1] + P[1][2]), dist(P[0][1] - 2 * P[0][2] + P[0][3], P[1][1] - 2 * P[1][2] + P[1][3]));
  360.     double N = 1 + sqrt(3 * D);
  361.     double dt = 1 / N;
  362.     double t = dt;
  363.     vector<int> P1, P2;
  364.     P1 = R3(0, P); //нач точка
  365.     while (t <= 1)
  366.     {
  367.         P2 = R3(t, P);
  368.         t += dt;
  369.         DrawLine(P1[0], P1[1], P2[0], P2[1], color);
  370.         P1 = P2;
  371.     }
  372.     P2 = R3(1, P);
  373.     DrawLine(P1[0], P1[1], P2[0], P2[1], color);
  374. }
  375.  
  376.  
  377. int PolyTypeConvOrient(vector<vector<int>>& P, int& t) //проверка на ориентацию
  378. {
  379.     t = -1;
  380.     if (P[0].size() <= 2)
  381.     {
  382.         gfDrawText(300, 300, "Not polygon", RGBPIXEL::Cyan());
  383.         return -1;
  384.     }
  385.     int type0 = Classify(P[0][0], P[1][0], P[0][1], P[1][1], P[0][2], P[1][2]);
  386.     for (int j = 0; j < P[0].size() - 1; j++)
  387.         for (int i = j + 2; i < P[0].size() + j - 1; i++)
  388.         {
  389.             int type = Classify(P[0][j], P[1][j], P[0][j + 1], P[1][j + 1], P[0][i % P[0].size()], P[1][i % P[0].size()]);
  390.             if (type == DEST || type == ORIGIN || type == BEYOND || type == BEHIND)
  391.             {
  392.                 gfDrawText(300, 300, "Not polygon", RGBPIXEL::Cyan());
  393.                 return -1;
  394.             }
  395.             if (type != type0)
  396.                 return NON_CONVEX;
  397.         }
  398.     if (type0 == LEFT)
  399.         t = CLOCKWISE;  //по часовой(система левосторонняя)
  400.     if (type0 == RIGHT)
  401.         t = COUNTERCLOCKWISE;
  402.     return CONVEX;
  403. }
  404.  
  405. void ClipLine(vector<vector<int>>& line, vector<vector<int>>& Poly, RGBPIXEL color) //(лек)
  406. {
  407.     int n = Poly[0].size();  //количество вершин(точек)
  408.     int trigger = -1; //отвечает за по\против часовой (ориентация)
  409.     int type = PolyTypeConvOrient(Poly, trigger);
  410.     if (type == NON_CONVEX)
  411.         gfDrawText(500, 100, "Невыпуклый", RGBPIXEL::Red());
  412.     else
  413.     {
  414.         if (trigger == CLOCKWISE) //переворачиваем, делаем копию buff и меняем
  415.         {
  416.             vector<vector<int>> buff = Poly;
  417.             for (int j = 0; j < 2; j++)
  418.                 for (int i = 1; i < n; i++)
  419.                 {
  420.                     buff[j][i] = Poly[j][n - i];
  421.                 }
  422.             Poly = buff;
  423.         }
  424.         double t0 = 0, t1 = 1, t;
  425.         int sx = line[0][1] - line[0][0];
  426.         int sy = line[1][1] - line[1][0];
  427.         int nx, ny;
  428.         double num, denom;
  429.         for (int i = 0; i < n; i++)
  430.         {
  431.             nx = Poly[1][(i + 1) % n] - Poly[1][i];
  432.             ny = Poly[0][i] - Poly[0][(i + 1) % n];
  433.             denom = nx * sx + ny * sy;
  434.             num = nx * (line[0][0] - Poly[0][i]) + ny * (line[1][0] - Poly[1][i]);
  435.             if (abs(denom) > 0.01)
  436.             {
  437.                 t = -num / denom;
  438.                 if (denom > 0)
  439.                 {
  440.                     if (t > t0)
  441.                         t0 = t;
  442.  
  443.                 }
  444.                 else
  445.                 {
  446.                     if (t < t1)
  447.                         t1 = t;
  448.                 }
  449.             }
  450.         }
  451.         if (t0 <= t1) //&& t1>0)
  452.             DrawLine(int(line[0][0] + t0 * sx), int(line[1][0] + t0 * sy), int(line[0][0] + t1 * sx), int(line[1][0] + t1 * sy), color);
  453.     }
  454.  
  455. }
  456.  
  457.  
  458. // Вызывается один раз в самом начале при инициализации приложения
  459. bool gfInitScene()
  460. {
  461.     gfSetWindowSize( 640, 480 );
  462.  
  463.     gfSetPixel( 20, 20, RGBPIXEL(255, 255, 0) );
  464.    
  465.     vector<vector<int>> Poly = { {60, 60, 300, 300} ,{60,300,300,60} };
  466.     vector<vector<int>> Poly2 = { {60, 300, 60, 300} ,{60,300,300,60} };
  467.     DrawPolygon(Poly, RGBPIXEL::Cyan());
  468.     //DrawPolygon(Poly2, RGBPIXEL::Cyan());
  469.     //PolyTypeConv(Poly);
  470.     //PolyTypeSimp(Poly);
  471.     DrawLine(10, 10, 500, 300, RGBPIXEL::Green());
  472.     vector<vector<int>> line = { {10, 500} ,{10, 300}};
  473.     //DrawBesie3(Poly, RGBPIXEL::Red());
  474.     ClipLine(line, Poly, RGBPIXEL::Red());
  475.  
  476.     //FillingEO(Poly, RGBPIXEL::Red());
  477.     //FillingNZW(Poly2, RGBPIXEL::Red());
  478.     //gfDrawRectangle( 100, 120, 170, 150, RGBPIXEL(255, 255, 0) );
  479.     //gfDrawText( 200, 200, "Hello World", RGBPIXEL(0, 128, 255));
  480.     //gfDisplayMessage("Message!");
  481.  
  482.     return true;
  483. }
  484.  
  485. // Вызывается в цикле до момента выхода из приложения.
  486. // Следует использовать для создания анимационных эффектов
  487. void gfDrawScene()
  488. {
  489.     //gfClearScreen(RGBPIXEL::Black());
  490.  
  491.     //static int x = 0;
  492.     //gfDrawRectangle(x, 100, x + 50, 130, RGBPIXEL::Blue());
  493.     //x = (x + 1) % gfGetWindowWidth() ;
  494.  
  495.     //int x = gfGetMouseX(),
  496.     //    y = gfGetMouseY();
  497.     //gfDrawRectangle(x - 10, y - 10, x + 10, y + 10, RGBPIXEL::Green());
  498. }
  499.  
  500. // Вызывается один раз перед выходом из приложения.
  501. // Следует использовать для освобождения выделенных
  502. // ресурсов (памяти, файлов и т.п.)
  503. void gfCleanupScene()
  504. {
  505. }
  506.  
  507. // Вызывается когда пользователь нажимает левую кнопку мыши
  508. void gfOnLMouseClick( int x, int y )
  509. {
  510.     x; y;
  511.     gfDrawRectangle(x - 10, y - 10, x + 10, y + 10, RGBPIXEL::Green());
  512. }
  513.  
  514. // Вызывается когда пользователь нажимает правую кнопку мыши
  515. void gfOnRMouseClick( int x, int y )
  516. {
  517.     x; y;
  518. }
  519.  
  520. // Вызывается когда пользователь нажимает клавишу на клавиатуре
  521. void gfOnKeyDown( UINT key )
  522. {
  523.     key;
  524.  
  525.     if( key == 'A' )
  526.         gfDisplayMessage( "'A' key has been pressed" );
  527. }
  528.  
  529. // Вызывается когда пользователь отжимает клавишу на клавиатуре
  530. void gfOnKeyUp( UINT key )
  531. {
  532.     key;
  533.  
  534.     //if( key == 'B' )
  535.     //    gfDisplayMessage( "'B' key has been un-pressed" );
  536. }
RAW Paste Data