Guest User

Untitled

a guest
Mar 22nd, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.27 KB | None | 0 0
  1. #include <iostream>
  2. #include <windows.h>
  3. #include <time.h>
  4. #include <math.h>
  5. using namespace std;
  6.  
  7. #pragma comment(lib,"msimg32.lib")
  8.  
  9. /**************************************************************************************************************/
  10. HWND hwnd = GetConsoleWindow();
  11. HDC hdc = GetDC(hwnd);
  12. HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
  13. COORD c;
  14.  
  15.  
  16. POINT p; //***** для функции MoveToEx
  17.  
  18. const float OneDegree = 3.14 / 180; //***** коэффициент перевода градусов в радианы и обратно
  19. const int GROUND = 200; //***** высота линии, вдоль которой покатится фигура
  20.  
  21. //***** градусы = радианы / OneDegree ( для переменных и массивов этой программы, хранящих углы )
  22. //***** радианы = градусы * OneDegree ( для математических функций sinf, cosf, atanf... )
  23.  
  24.  
  25. /**************************************************************************************************************/
  26. /*********************************************** К Л А С С ****************************************************/
  27. class POLYGON
  28. {
  29. //***** поля класса:
  30. int maxTopNumber; //***** наибольший порядковый номер вершины (т.е. кол-во вершин)
  31. int leftGroundTop, rightGroundTop; //***** порядковые номера ОПОРНЫХ вершин многоугольника
  32. int gorizontalOffset; //***** стартовый горизонтальный сдвиг фигуры
  33.  
  34. int *PolarRadius; float *PolarAngle; //***** массивы ПОЛЯРНЫХ координат вершин относительно центральной точки
  35. int *X, *Y; //***** массивы ДЕКАРТОВЫХ координат вершин многоугольника
  36.  
  37. int *LeftNumber, *RightNumber; //***** массивы "соседей" каждой вершины
  38. bool *Convexity; //***** массив выпуклостей вершин
  39. HBRUSH *Brush; //***** массив заливок
  40.  
  41. //***** методы класса:
  42. void FillConvexity();
  43. void FindBeginRotationAngle();
  44. void PolarToDecart(float);
  45. void FineRotateAndShow(int, int);
  46. void Show(bool);
  47.  
  48. public:
  49. POLYGON();
  50. ~POLYGON();
  51.  
  52. void Move();
  53. };
  54.  
  55. /**************************************************************************************************************/
  56. /************************************************ конструктор *************************************************/
  57.  
  58. POLYGON::POLYGON()
  59. {
  60. maxTopNumber = rand() % 8 + 4;
  61. leftGroundTop = rightGroundTop = 1;
  62. gorizontalOffset = 200;
  63.  
  64. //***** выделение динамической памяти под массивы атрибутов вершин многоугольника
  65. PolarRadius = new int[maxTopNumber + 1]; PolarAngle = new float[maxTopNumber + 1];
  66. X = new int[maxTopNumber + 1]; Y = new int[maxTopNumber + 1];
  67.  
  68. LeftNumber = new int[maxTopNumber + 1]; RightNumber = new int[maxTopNumber + 1];
  69. Brush = new HBRUSH[maxTopNumber + 1]; Convexity = new bool[maxTopNumber + 1];
  70.  
  71. //***** инициализация массивов атрибутов
  72. PolarRadius[0] = PolarAngle[0] = X[0] = Y[0] = 0; //***** в 0-ых ячейках находятся координаты "центральной" точки многоугольника
  73. Brush[0] = CreateSolidBrush(RGB(0, 0, 0));
  74.  
  75. for (int topNumber = 1; topNumber <= maxTopNumber; topNumber++)
  76. {
  77. //***** инициализация вершин в полярных координатах:
  78. PolarRadius[topNumber] = rand() % 100 + 30;
  79. PolarAngle[topNumber] = rand() % (360 / maxTopNumber) + (topNumber - 1) * (360 / maxTopNumber);
  80.  
  81. //***** конверсия полярных координат в декартовы:
  82. X[topNumber] = PolarRadius[topNumber] * cosf(PolarAngle[topNumber] * OneDegree);
  83. Y[topNumber] = PolarRadius[topNumber] * sinf(PolarAngle[topNumber] * OneDegree);
  84.  
  85. //***** заполнение массива заливок секторов:
  86. Brush[topNumber] = CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256));
  87.  
  88. //***** заполнение массивов соседей каждой точки:
  89. LeftNumber[topNumber] = topNumber + 1;
  90. RightNumber[topNumber] = topNumber - 1;
  91. if (topNumber == 1) RightNumber[topNumber] = maxTopNumber;
  92. else if (topNumber == maxTopNumber) LeftNumber[topNumber] = 1;
  93. }
  94.  
  95. //***** проведение горизонтальной линии, по которой покатится многоугольник:
  96. HPEN bluePen = CreatePen(PS_SOLID, 1, RGB(0, 0, 255));
  97. MoveToEx(hdc, 0, (GROUND + 1), &p); SelectObject(hdc, bluePen); LineTo(hdc, 600, GROUND + 1);
  98. MoveToEx(hdc, 200, 0, &p); SelectObject(hdc, bluePen); LineTo(hdc, 200, 300);
  99.  
  100. FillConvexity();
  101. }
  102.  
  103.  
  104. /*******************************************************************************************************************/
  105. /************************************* заполнение массивов выпуклостей вершин ***************************************/
  106.  
  107. void POLYGON::FillConvexity()
  108. {
  109. int prevTop, nextTop, prevAng, nextAng;
  110. float k1 = 1, k2 = 1, b1 = 1;
  111. float pX, pY, dist;
  112.  
  113. for (int topNumber = 1; topNumber <= maxTopNumber; topNumber++) //***** topNumber - номер текущей вершины
  114. {
  115. prevTop = topNumber - 1; prevAng = PolarAngle[prevTop]; //***** угловая точка, предыдущая относительно текущей точки
  116. nextTop = topNumber + 1; nextAng = PolarAngle[nextTop]; //***** угловая точка, следующая за текущей точкой (по часовой стрелке)
  117. if (topNumber == 1) {
  118. prevTop = maxTopNumber; prevAng = 360 - PolarAngle[prevTop];
  119. }
  120. else if (topNumber == maxTopNumber) {
  121. nextTop = 1; nextAng = 360 + PolarAngle[nextTop];
  122. }
  123.  
  124. //***** выпуклости (добавить условие X[ nextTop ] != X[ prevTop ]
  125. if (nextAng - prevAng < 180)
  126. {
  127. k1 = ((float)Y[nextTop] - Y[prevTop]) / (X[nextTop] - X[prevTop]);
  128. b1 = Y[nextTop] - k1 * X[nextTop];
  129. k2 = (float)Y[topNumber] / X[topNumber];
  130.  
  131. //***** координаты точки пересечения 2-х отрезков:
  132. //***** первый отрезок соединяет следующую и предыдущую (относительно текущей точки) угловые точки
  133. //***** второй соединяет центральную точку и текущую точку
  134. pX = b1 / (k2 - k1);
  135. pY = k2 * pX;
  136.  
  137. dist = sqrtf(pX*pX + pY*pY); //***** расстояние от точки (pX, pY) до начала координат
  138.  
  139. if (dist > PolarRadius[topNumber]) Convexity[topNumber] = false;
  140. else Convexity[topNumber] = true;
  141. }
  142. else Convexity[topNumber] = true;
  143.  
  144. }
  145.  
  146. FindBeginRotationAngle();
  147. }
  148.  
  149.  
  150. /************************************************************************************************************************/
  151. /****************************** нахождение угла поворота для установки в исходную позицию *******************************/
  152.  
  153. void POLYGON::FindBeginRotationAngle()
  154. {
  155. float rotationAngle;
  156.  
  157. //***** ищем выпуклую вершину, начиная с первой, которая послужит правой опорной точкой:
  158. for (rightGroundTop = 1; Convexity[rightGroundTop] == false; rightGroundTop++);
  159.  
  160. //***** ищем выпуклую вершину, начиная со следующей за правой опорной точкой, которая послужит левой опорной точкой:
  161. for (leftGroundTop = rightGroundTop + 1; Convexity[leftGroundTop] == false; leftGroundTop++);
  162.  
  163. //***** "грубый" расчет угла поворота фигуры
  164. if (X[rightGroundTop] != X[leftGroundTop])
  165. rotationAngle = atanf((float)(Y[leftGroundTop] - Y[rightGroundTop]) /
  166. (X[rightGroundTop] - X[leftGroundTop])) / OneDegree;
  167. else
  168. rotationAngle = 90;
  169.  
  170. PolarToDecart(rotationAngle);
  171.  
  172. FineRotateAndShow(leftGroundTop, rightGroundTop);
  173.  
  174. //***** временная задержка отображения фигуры в стартовом положении:
  175. Sleep(100);
  176. }
  177.  
  178. /**********************************************************************************************************************/
  179. /**************** подгонка угла поворота фигуры, чтобы обе опорные вершины оказались на уровне линии ******************/
  180.  
  181. void POLYGON::FineRotateAndShow(int leftTop, int rightTop)
  182. {
  183. int direction; float fineTuneAngle = 0.1;
  184.  
  185. //***** требуется ли подгонка фигуры с большей точностью?
  186. if (Y[leftTop] > Y[rightTop])
  187. direction = 1;
  188. else if (Y[leftTop] < Y[rightTop])
  189. direction = -1;
  190. else
  191. return;
  192.  
  193. Show(false);
  194.  
  195. for (int i = 0; Y[leftTop] != Y[rightTop] && i < 10; i++)
  196. PolarToDecart(fineTuneAngle * direction);
  197.  
  198. Show(true);
  199. }
  200.  
  201.  
  202. /**********************************************************************************************************************/
  203. /********** пересчет декартовых координат точек для поворота фигуры вокруг ЦЕНТРАЛЬНОЙ точки на заданный угол *************/
  204.  
  205. void POLYGON::PolarToDecart(float ang)
  206. {
  207. for (int topNumber = 1; topNumber <= maxTopNumber; topNumber++)
  208. {
  209. PolarAngle[topNumber] += ang;
  210. X[topNumber] = PolarRadius[topNumber] * cosf(PolarAngle[topNumber] * OneDegree); //***** конверсия полярных координат в декартовы
  211. Y[topNumber] = PolarRadius[topNumber] * sinf(PolarAngle[topNumber] * OneDegree);
  212. }
  213. }
  214.  
  215.  
  216. /********************************************************************************************************************/
  217. /************************ управление выводом фигуры, которая катится вдоль горизонтальной прямой ********************/
  218. void POLYGON::Move()
  219. {
  220. int prevRightGroundTop, nextRightGroundTop;
  221.  
  222. while (gorizontalOffset < 800)
  223. {
  224. //***** ищем следующую правую опорную точку
  225. for (nextRightGroundTop = RightNumber[rightGroundTop]; Convexity[nextRightGroundTop] == false;
  226. nextRightGroundTop = RightNumber[nextRightGroundTop]);
  227.  
  228. Show(true);
  229.  
  230. //***** вращаем фигуру вокруг неподвижной текущей правой опорной точки до тех пор,
  231. //***** пока следуюшая правая опорная точка не коснется линии
  232. while (Y[nextRightGroundTop] < Y[rightGroundTop])
  233. {
  234. //***** выдерживаем время и стираем фигуру в старом положении:
  235. Sleep(10);
  236. Show(false);
  237.  
  238. //***** фактически вращение фигуры происходит вокруг ЦЕНТРАЛЬНОЙ точки, имеющей декартовы координаты (0,0) - так проще
  239. PolarToDecart(1);
  240.  
  241. //***** однако при выводе смещение подбирается каждый раз таким образом,
  242. //***** чтобы правая опорная вершина оказывалась в одном и том же месте экрана
  243. Show(true);
  244.  
  245.  
  246. }
  247.  
  248. //***** осуществляем подгонку фигуры:
  249. FineRotateAndShow(rightGroundTop, nextRightGroundTop);
  250.  
  251. gorizontalOffset += X[nextRightGroundTop] - X[rightGroundTop];
  252.  
  253. //***** делаем следущую правую опорную точку текущей:
  254. rightGroundTop = nextRightGroundTop;
  255.  
  256.  
  257. }
  258. }
  259.  
  260. /********************************************************************************************************************/
  261. /********************************* отображение фигуры в ее текущем положении на консоли ****************************/
  262.  
  263. void POLYGON::Show(bool v)
  264. {
  265. HPEN pen = CreatePen(PS_SOLID, 1, RGB(255 * v, 255 * v, 255 * v));
  266.  
  267. int midX, midY;
  268. int offsetX = gorizontalOffset - X[rightGroundTop];
  269. int offsetY = GROUND - Y[rightGroundTop];
  270.  
  271.  
  272. MoveToEx(hdc, offsetX, offsetY, &p); //***** установка кисти в центральную точку
  273.  
  274. for (int topNumber = 1; topNumber <= maxTopNumber; topNumber++) //***** соединение точек линиями
  275. {
  276. SelectObject(hdc, pen);
  277. LineTo(hdc, (X[topNumber] + offsetX), (Y[topNumber] + offsetY)); //***** от центральной к текущей угловой точке
  278. LineTo(hdc, (X[LeftNumber[topNumber]] + offsetX), (Y[LeftNumber[topNumber]] + offsetY));
  279. LineTo(hdc, offsetX, offsetY); //***** к центральной точке
  280.  
  281. //***** вычисление внутренней точки сектора, образованного текущей точкой, следующей и центральной точками:
  282. midX = (X[LeftNumber[topNumber]] + X[topNumber]) / 4;
  283. midY = (Y[LeftNumber[topNumber]] + Y[topNumber]) / 4;
  284.  
  285. SelectObject(hdc, Brush[topNumber * v]);
  286. FloodFill(hdc, (midX + offsetX), (midY + offsetY), RGB(255 * v, 255 * v, 255 * v));
  287.  
  288. //Sleep (100);
  289. }
  290.  
  291. }
  292.  
  293.  
  294. /***************************************************************************************************************/
  295. /*************************************************** M A I N ***************************************************/
  296. void main()
  297. {
  298. system("title Rolling Polygones");
  299. srand(time(0));
  300. system("mode con cols=120 lines=20");
  301.  
  302. while (true)
  303. {
  304. POLYGON figure;
  305. figure.Move();
  306. }
  307. }
  308.  
  309.  
  310. /**************************************************************************************************************/
  311. /************************************************ деструктор *************************************************/
  312. POLYGON :: ~POLYGON()
  313. {
  314. delete[]PolarRadius;
  315. delete[]PolarAngle;
  316. delete[]X;
  317. delete[]Y;
  318. delete[]LeftNumber;
  319. delete[]RightNumber;
  320. delete[]Convexity;
  321. delete[]Brush;
  322. }
Add Comment
Please, Sign In to add comment