Tvor0zhok

КГ лабораторная №4

Mar 26th, 2022 (edited)
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.45 KB | None | 0 0
  1. // Matrix.h
  2.  
  3. #pragma once
  4.  
  5. class vec2
  6. {
  7. public:
  8.  
  9. float x, y;
  10.  
  11. // конструкторы
  12. vec2() {}
  13. vec2(float a, float b) : x(a), y(b) {}
  14. };
  15.  
  16. class vec3
  17. {
  18. public:
  19.  
  20. float x, y, z;
  21.  
  22. // конструкторы
  23. vec3() {}
  24. vec3(float a, float b, float c) : x(a), y(b), z(c) {}
  25. vec3(vec2 v, float z) : vec3(v.x, v.y, z) {}
  26.  
  27. // перегрузка операций *= , * и []
  28.  
  29. vec3& operator *= (const vec3& v)
  30. {
  31. x *= v.x;
  32. y *= v.y;
  33. z *= v.z;
  34.  
  35. return *this;
  36. }
  37.  
  38. const vec3 operator * (const vec3& v)
  39. {
  40. return vec3(*this) *= v; // делаем временную копию текущего объекта, которую
  41. } // домножаем на данный вектор, и возвращаем ее как результат
  42.  
  43. float& operator [] (int i)
  44. {
  45. return ((float*)this)[i]; // ссылку на текующий объект рассматриваем как ссылку на 0-ой элемент
  46. } // массива значений типа float, после чего обращаемся к его i-ому элементу
  47. };
  48.  
  49. // скалярное умножение
  50. float dot(vec3 v1, vec3 v2)
  51. {
  52. vec3 tmp = v1 * v2; // вычисляем произведение соответствующих координат
  53. return tmp.x + tmp.y + tmp.z; // и возвращаем их сумму
  54. }
  55.  
  56. class mat3
  57. {
  58. public:
  59.  
  60. vec3 row1, row2, row3; // строки матрицы
  61.  
  62. // конструкторы
  63. mat3() {}
  64. mat3(vec3 r1, vec3 r2, vec3 r3) : row1(r1), row2(r2), row3(r3) {}
  65.  
  66. mat3(float a) // диагональная матрица
  67. {
  68. row1 = vec3(a, 0.f, 0.f);
  69. row2 = vec3(0.f, a, 0.f);
  70. row3 = vec3(0.f, 0.f, a);
  71. }
  72.  
  73. // перегрузка операции []
  74.  
  75. vec3& operator [] (int i)
  76. {
  77. return ((vec3*)this)[i]; // массив значений типа vec3
  78. }
  79.  
  80. // транспонирование матрицы
  81.  
  82. mat3 transpose()
  83. {
  84. mat3 tmp(*this); // временная копия матрицы
  85.  
  86. for (int i = 0; i < 3; ++i)
  87. for (int j = 0; j < 3; ++j)
  88. (*this)[i][j] = tmp[j][i]; // заменяем элементы текущего объекта
  89. // из временной копии
  90.  
  91. return *this;
  92. }
  93.  
  94. // перегрузка оператора *
  95.  
  96. const vec3 operator * (const vec3& v)
  97. {
  98. vec3* res = new(vec3); // создаем новый вектор-результат
  99.  
  100. for (int i = 0; i < 3; ++i)
  101. (*res)[i] = dot((*this)[i], v); // i-ый элемент веткора - скалярное произведение
  102.  
  103. return *res;
  104. }
  105.  
  106. // перемножение матриц (*= и *)
  107. // 1. B -> B.transpose()
  108. // 2. С = A * B.transpose()
  109. // 3. С -> C.transpose()
  110.  
  111. mat3& operator *= (const mat3& m)
  112. {
  113. mat3 A(*this), B(m); // копии исходных матриц
  114. B.transpose();
  115.  
  116. for (int i = 0; i < 3; ++i)
  117. (*this)[i] = A * B[i]; // в i-ую строку текущего объекта записываем результат перемножения
  118. // 1-ой матрицы с i-ой строкой транспонированной матрицы
  119.  
  120. return (*this).transpose(); // транспонируем и получаем ответ
  121. }
  122.  
  123. const mat3 operator * (const mat3& m)
  124. {
  125. return mat3(*this) *= m;
  126. }
  127. };
  128.  
  129. vec2 normalize(vec3 v)
  130. {
  131. return vec2(v.x / v.z, v.y / v.z);
  132. }
  133.  
  134. // Transform.h
  135.  
  136. #pragma once
  137. #include "Matrix.h"
  138. #include <math.h>
  139.  
  140. // матрица переноса
  141. mat3 translate(float Tx, float Ty)
  142. {
  143. mat3* res = new mat3(1.f); // матрица-результат
  144.  
  145. (*res)[0][2] = Tx; // поменяли значения
  146. (*res)[1][2] = Ty; // в последнем столбце
  147.  
  148. return *res;
  149. }
  150.  
  151. // матрица масштабирования
  152. mat3 scale(float Sx, float Sy)
  153. {
  154. mat3* res = new mat3(1.f); // матрица-результат
  155.  
  156. (*res)[0][0] = Sx; // поменяли значения
  157. (*res)[1][1] = Sy; // на главной диагонали
  158.  
  159. return *res;
  160. }
  161.  
  162. // перегрузка: Sx = Sy = S
  163. mat3 scale(float S) { return scale(S, S); }
  164.  
  165. // матрица поворота (относительно начала координат против часовой стрелки)
  166. mat3 rotate(float theta)
  167. {
  168. mat3* res = new mat3(1.f); // матрица-результат
  169.  
  170. (*res)[0][0] = (*res)[1][1] = (float)cos(theta); // заполнили главную диагональ
  171. (*res)[0][1] = (float)sin(theta); // синус в 1-ой строке (с плюсом)
  172. (*res)[1][0] = -(float)sin(theta); // синус во 2-ой строке (с минусом)
  173.  
  174. return *res;
  175. }
  176.  
  177. // матрица зеркального отображения относительно оси Ox
  178. mat3 mirrorX()
  179. {
  180. mat3* res = new mat3(1.f);
  181. (*res)[1][1] = -1.f;
  182.  
  183. return *res;
  184. }
  185.  
  186. // матрица зеркального отображения относительно оси Oy
  187. mat3 mirrorY()
  188. {
  189. mat3* res = new mat3(1.f);
  190. (*res)[0][0] = -1.f;
  191.  
  192. return *res;
  193. }
  194.  
  195. // Figure.h
  196.  
  197. #pragma once
  198. #include "Matrix.h"
  199. #include <vector>
  200. using namespace std;
  201.  
  202. class path
  203. {
  204. public:
  205.  
  206. vector <vec2> vertices; // последовательность точек
  207. vec3 color; // цвет, разбитый на составляющие RGB
  208. float thickness; // толщина линии
  209.  
  210. path(vector <vec2> verts, vec3 col, float thickn)
  211. {
  212. vertices = verts;
  213. color = col;
  214. thickness = thickn;
  215. }
  216. };
  217.  
  218. class model
  219. {
  220. public:
  221.  
  222. vector <path> figure; // составляющие рисунка
  223. mat3 modelM; // модельная матрица (матрица преобразований)
  224.  
  225. model(vector <path> fig, mat3 mat) // конструктор
  226. {
  227. figure = fig;
  228. modelM = mat;
  229. }
  230. };
  231.  
  232. // MyForm.h
  233.  
  234. #pragma once
  235.  
  236. namespace Moskvitin {
  237.  
  238. using namespace System;
  239. using namespace System::ComponentModel;
  240. using namespace System::Collections;
  241. using namespace System::Windows::Forms;
  242. using namespace System::Data;
  243. using namespace System::Drawing;
  244. using namespace std;
  245.  
  246. mat3 T = mat3(1.f); // матрица, в которой накапливаются все преобразования
  247. mat3 initT; // матрица начального преобразования
  248.  
  249. vector<model> models;
  250.  
  251. float Vx, Vy; // размеры рисунка по горизонтали и вертикали
  252. float aspectFig; // соотношение сторон рисунка
  253.  
  254. /// <summary>
  255. /// Сводка для MyForm
  256. /// </summary>
  257. public ref class MyForm : public System::Windows::Forms::Form
  258. {
  259. public:
  260. MyForm(void)
  261. {
  262. InitializeComponent();
  263. //
  264. //TODO: добавьте код конструктора
  265. //
  266. }
  267.  
  268. protected:
  269. /// <summary>
  270. /// Освободить все используемые ресурсы.
  271. /// </summary>
  272. ~MyForm()
  273. {
  274. if (components)
  275. {
  276. delete components;
  277. }
  278. }
  279. private: System::Windows::Forms::OpenFileDialog^ openFileDialog;
  280. protected:
  281. private: System::Windows::Forms::Button^ btnOpen;
  282.  
  283. private:
  284. /// <summary>
  285. /// Обязательная переменная конструктора.
  286. /// </summary>
  287. System::ComponentModel::Container ^components;
  288.  
  289. #pragma region Windows Form Designer generated code
  290. /// <summary>
  291. /// Требуемый метод для поддержки конструктора — не изменяйте
  292. /// содержимое этого метода с помощью редактора кода.
  293. /// </summary>
  294. void InitializeComponent(void)
  295. {
  296. this->openFileDialog = (gcnew System::Windows::Forms::OpenFileDialog());
  297. this->btnOpen = (gcnew System::Windows::Forms::Button());
  298. this->SuspendLayout();
  299. //
  300. // openFileDialog
  301. //
  302. this->openFileDialog->DefaultExt = L"txt";
  303. this->openFileDialog->Filter = L"Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)|*.*";
  304. this->openFileDialog->Title = L"Открыть файл";
  305. //
  306. // btnOpen
  307. //
  308. this->btnOpen->Anchor = static_cast<System::Windows::Forms::AnchorStyles>((System::Windows::Forms::AnchorStyles::Top | System::Windows::Forms::AnchorStyles::Right));
  309. this->btnOpen->Location = System::Drawing::Point(178, 12);
  310. this->btnOpen->Name = L"btnOpen";
  311. this->btnOpen->Size = System::Drawing::Size(88, 31);
  312. this->btnOpen->TabIndex = 0;
  313. this->btnOpen->Text = L"Открыть";
  314. this->btnOpen->UseVisualStyleBackColor = true;
  315. this->btnOpen->Click += gcnew System::EventHandler(this, &MyForm::btnOpen_Click);
  316. //
  317. // MyForm
  318. //
  319. this->AutoScaleDimensions = System::Drawing::SizeF(9, 20);
  320. this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
  321. this->ClientSize = System::Drawing::Size(278, 244);
  322. this->Controls->Add(this->btnOpen);
  323. this->KeyPreview = true;
  324. this->MinimumSize = System::Drawing::Size(230, 170);
  325. this->Name = L"MyForm";
  326. this->Text = L"MyForm";
  327. this->Load += gcnew System::EventHandler(this, &MyForm::MyForm_Load);
  328. this->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &MyForm::MyForm_Paint);
  329. this->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &MyForm::MyForm_KeyDown);
  330. this->Resize += gcnew System::EventHandler(this, &MyForm::MyForm_Resize);
  331. this->ResumeLayout(false);
  332.  
  333. }
  334. #pragma endregion
  335.  
  336. private: float left = 30, right = 100, top = 20, bottom = 50; // расстояния до границ окна
  337. float minX = left, maxX; // диапазон изменения координат x
  338. float minY = top, maxY; // диапазон изменения координат y
  339. float Wcx = left, Wcy; // координаты левого нижнего угла прямоугольника
  340. float Wx, Wy; // ширина и высота прямоугольника
  341.  
  342. // инициализация остальных параметров
  343.  
  344. private: System::Void rectCalc()
  345. {
  346. maxX = ClientRectangle.Width - right; // диапазон изменения координат x
  347. maxY = ClientRectangle.Height - bottom; // диапазон изменения координат y
  348. Wcy = maxY; // координаты левого нижнего угла прямоугольника
  349. Wx = maxX - left; // ширина прямоугольника
  350. Wy = maxY - top;
  351. }
  352.  
  353. private: System::Void MyForm_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) {
  354. // описываем переменную g - область рисования, ссылку на объект типа System::Drawing::Graphics^
  355. Graphics^ g = e->Graphics;
  356.  
  357. // черная ручка
  358. Pen^ rectPen = gcnew Pen(Color::Black, 2);
  359.  
  360. // рисуем область видимости
  361. g->DrawRectangle(rectPen, left, top, Wx, Wy);
  362.  
  363. for (int k = 0; k < models.size(); ++k) // цикл по рисункам
  364. {
  365. vector<path> figure = models[k].figure; // список ломаных очередного рисунка
  366. mat3 TM = T * models[k].modelM; // матрица общего преобразования рисунка
  367.  
  368. for (int i = 0; i < figure.size(); ++i)
  369. {
  370. path lines = figure[i]; // очередная ломаная линия
  371. Pen^ pen = gcnew Pen(Color::FromArgb(lines.color.x, lines.color.y, lines.color.z));
  372. pen->Width = lines.thickness;
  373.  
  374. vec2 start = normalize(TM * vec3(lines.vertices[0], 1.0)); // начальная точка первого отрезка
  375.  
  376. for (int j = 1; j < lines.vertices.size(); j++) // цикл по конечным точкам (от единицы)
  377. {
  378. vec2 end = normalize(TM * vec3(lines.vertices[j], 1.0)); // конечная точка
  379. vec2 tmpEnd = end; // продублировали координаты точки для будущего использования
  380.  
  381. if (clip(start, end, minX, minY, maxX, maxY)) { // если отрезок видим
  382. g->DrawLine(pen, start.x, start.y, end.x, end.y); // отрисовка видимых частей
  383. } // после отсечения, start и end - концы видимой части отрезка
  384.  
  385. start = tmpEnd; // конечная точка неотсеченного отрезка становится начальной точкой следующего
  386. }
  387. }
  388. }
  389.  
  390.  
  391.  
  392.  
  393. }
  394.  
  395. private: System::Void MyForm_Resize(System::Object^ sender, System::EventArgs^ e) {
  396. // Добавляем устойчивость рисунка относительно изменения размера окна
  397. Refresh();
  398. // передподсчет сторон прямоугольника
  399. rectCalc();
  400. }
  401.  
  402. private: System::Void MyForm_Load(System::Object^ sender, System::EventArgs^ e) {
  403. rectCalc();
  404. }
  405.  
  406. private: System::Void MyForm_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e) {
  407. switch (e->KeyCode)
  408. {
  409. // поворот на 0.01 радиан против часовой стрелки
  410. case Keys::Q:
  411. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T; // перенос начала координат в центр области видимости
  412. T = rotate(0.01f) * T; // поворот
  413. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T; // перенос начала координат обратно
  414. break;
  415. // сдвиг изображения вверх на 1 пиксель
  416. case Keys::W:
  417. T = translate(0.f, -1.f) * T;
  418. break;
  419. // сброс всех преобразований
  420. case Keys::Escape:
  421. T = initT;
  422. break;
  423. // поворот на 0.01 радиан по часовой стрелке
  424. case Keys::E:
  425. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T; // перенос начала координат в центр области видимости
  426. T = rotate(-0.01f) * T; // поворот
  427. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T; // перенос начала координат обратно
  428. break;
  429. // сдвиг изображения вниз на 1 пиксель
  430. case Keys::S:
  431. T = translate(0.f, 1.f) * T;
  432. break;
  433. // сдвиг изображения влево на 1 пиксель
  434. case Keys::A:
  435. T = translate(-1.f, 0.f) * T;
  436. break;
  437. // сдвиг изображения вправо на 1 пиксель
  438. case Keys::D:
  439. T = translate(1.f, 0.f) * T;
  440. break;
  441. // поворот на 0.05 радиан по часовой стрелке
  442. case Keys::R:
  443. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T; // перенос начала координат в центр области видимости
  444. T = rotate(-0.05f) * T;
  445. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T; // перенос начала координат обратно
  446. break;
  447. // поворот на 0.05 радиан против часовой стрелки
  448. case Keys::Y:
  449. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T; // перенос начала координат в центр области видимости
  450. T = rotate(0.05f) * T;
  451. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T; // перенос начала координат обратно
  452. break;
  453. // сдвиг изображения вверх на 10 пикселей
  454. case Keys::T:
  455. T = translate(0.f, -10.f) * T;
  456. break;
  457. // сдвиг изображения вниз на 10 пикселей
  458. case Keys::G:
  459. T = translate(0.f, 10.f) * T;
  460. break;
  461. // сдвиг изображения влево на 10 пикселей
  462. case Keys::F:
  463. T = translate(-10.f, 0.f) * T;
  464. break;
  465. // сдвиг изображения вправо на 10 пикселей
  466. case Keys::H:
  467. T = translate(10.f, 0.f) * T;
  468. break;
  469. // увеличение изображения в 1.1 раз
  470. case Keys::Z:
  471. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T;
  472. T = scale(1.1f) * T;
  473. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T;
  474. break;
  475. // уменьшение изображения в 1.1 раз
  476. case Keys::X:
  477. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T;
  478. T = scale(10.f / 11.f) * T;
  479. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T;
  480. break;
  481. // зеркальное отражения относительно горизонтальной оси, проходящей через центр окна
  482. case Keys::U:
  483. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T;
  484. T = mirrorX() * T;
  485. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T;
  486. break;
  487. // зеркальное отражение относительно вертикальной оси, проходящей через центр окна
  488. case Keys::J:
  489. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T;
  490. T = mirrorY() * T;
  491. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T;
  492. break;
  493. // растяжение изображения по горизонтали в 1.1 раз
  494. case Keys::I:
  495. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T;
  496. T = scale(1.1f, 1.f) * T;
  497. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T;
  498. break;
  499. // сжатие изображения по горизонтали в 1.1 раз
  500. case Keys::K:
  501. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T;
  502. T = scale(10.f / 11.f, 1.f) * T;
  503. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T;
  504. break;
  505. // растяжение изображения по вертикали в 1.1 раз
  506. case Keys::O:
  507. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T;
  508. T = scale(1.f, 1.1f) * T;
  509. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T;
  510. break;
  511. // сжатие изображения по вертикали в 1.1 раз
  512. case Keys::L:
  513. T = translate(-Wcx - Wx / 2, -Wcy + Wy / 2) * T;
  514. T = scale(1.f, 10.f / 11.f) * T;
  515. T = translate(Wcx + Wx / 2, Wcy - Wy / 2) * T;
  516. break;
  517. default:break;
  518. }
  519.  
  520. Refresh();
  521. }
  522. private: System::Void btnOpen_Click(System::Object^ sender, System::EventArgs^ e) {
  523. if (openFileDialog->ShowDialog() == System::Windows::Forms::DialogResult::OK)
  524. {
  525. // в файловом диалоге нажата кнопка OK
  526.  
  527. // перезапись имени файла из openFileDialog->FileName в fileName
  528. wchar_t fileName[1024]; // переменная, в которой посимвольно сохраним имя файла
  529.  
  530. for (int i = 0; i < openFileDialog->FileName->Length; i++)
  531. fileName[i] = openFileDialog->FileName[i];
  532.  
  533. fileName[openFileDialog->FileName->Length] = '\0';
  534.  
  535. // объявление и открытие файла
  536.  
  537. ifstream in;
  538. in.open(fileName);
  539.  
  540. if (in.is_open())
  541. {
  542. // файл успешно открыт
  543.  
  544. models.clear(); // очищаем имеющийся список рисунков
  545.  
  546. mat3 M = mat3(1.f); // матрица для получения модельной матрицы
  547. mat3 initM; // матрица для начального преобразования каждого рисунка
  548. vector<mat3> transforms; // стек матриц преобразований
  549. vector<path> figure; // список ломаных очередного рисунка
  550.  
  551. // временные переменные для чтения из файла
  552. float thickness = 2; // толщина со значением по умолчанию 2
  553. float r, g, b; // составляющие цвета
  554. r = g = b = 0; // значение составляющих цвета по умолчанию (черный)
  555.  
  556. // непосредственно работа с файлом
  557.  
  558. string str; // строка, в которую считываем строки файла
  559. getline(in, str); // считываем из входного файла первую строку
  560. while (in) // если очередная строка считана успешно
  561. {
  562. // обрабатываем строку
  563. if ((str.find_first_not_of(" \t\r\n") != string::npos) && (str[0] != '#'))
  564. {
  565. // прочитанная строка не пуста и не комментарий
  566. stringstream s(str); // строковый поток из строки str
  567.  
  568. string cmd; // переменная для имени команды
  569. s >> cmd; // считываем имя команды
  570.  
  571. if (cmd == "frame") { // размеры изображения
  572. s >> Vx >> Vy; // считываем глобальные значение Vx и Vy
  573. aspectFig = Vx / Vy; // обновление соотношения сторон
  574.  
  575. // размеры прямоугольника
  576. float Wx = ClientRectangle.Width - left - right; // ширина прямоугольника
  577. float Wy = ClientRectangle.Height - top - bottom; // высота прямоугольника
  578.  
  579. // соотношение сторон прямоугольника
  580. float aspectRect = Wx / Wy;
  581.  
  582. // смещение центра рисунка с началом координат
  583. mat3 T1 = translate(-Vx / 2, -Vy / 2);
  584.  
  585. // масштабирование остается прежним, меняется только привязка
  586. // коэффициент увеличения при сохранении исходного соотношения сторон
  587. float S = aspectFig < aspectRect ? Wy / Vy : Wx / Vx;
  588. mat3 S1 = scale(S, -S);
  589.  
  590. // сдвиг точки привязки из начала координат в нужную позицию
  591. mat3 T2 = translate(Wx / 2 + Wcx, Wcy - Wy / 2);
  592.  
  593. // В initT совмещаем эти три преобразования (справа налево)
  594. initT = T2 * (S1 * T1);
  595.  
  596. T = initT;
  597. }
  598. else if (cmd == "color") { // цвет линии
  599. s >> r >> g >> b; // считываем три составляющие цвета
  600. }
  601. else if (cmd == "thickness") { // толщина линии
  602. s >> thickness; // считываем значение толщины
  603. }
  604. else if (cmd == "path") { // набор точек
  605. vector<vec2> vertices; // список точек ломаной
  606.  
  607. int N; // количество точек
  608. s >> N;
  609.  
  610. string str1; // дополнительная строка для чтения из файла
  611.  
  612. while (N > 0) { // пока не все точки считали
  613. getline(in, str1); // считываем в str1 из входного файла очередную строку
  614. // так как файл корректный, то на конец файла проверять не нужно
  615.  
  616. if ((str1.find_first_not_of(" \t\r\n") != string::npos) && (str1[0] != '#')) {
  617. // прочитанная строка не пуста и не комментарий
  618. // значит в ней пара координат
  619.  
  620. float x, y; // переменные для считывания
  621. stringstream s1(str1); // еще один строковый поток из строки str1
  622. s1 >> x >> y;
  623. vertices.push_back(vec2(x, y)); // добавляем точку в список
  624. N--; // уменьшаем счетчик после успешного считывания точки
  625. }
  626. }
  627. // все точки считаны, генерируем ломаную (path) и кладем ее в список figure
  628. figure.push_back(path(vertices, vec3(r, g, b), thickness));
  629. }
  630. else if (cmd == "model") { // начало описания нового рисунка
  631. float mVcx, mVcy, mVx, mVy; // параметры команды model
  632. s >> mVcx >> mVcy >> mVx >> mVy; // считываем значения переменных
  633.  
  634. float S = mVx / mVy < 1 ? 2.f / mVy : 2.f / mVx;
  635.  
  636. // сдвиг точки привязки из начала координат в нужную позицию
  637. // после которого проводим масштабирование
  638. initM = scale(S) * translate(-mVcx, -mVcy);
  639.  
  640. figure.clear();
  641. }
  642. else if (cmd == "figure") { // формирование новой модели
  643. models.push_back(model(figure, M * initM)); // добавляем рисунок в список
  644. }
  645. else if (cmd == "translate") { // перенос
  646. float Tx, Ty; // параметры преобразования переноса
  647. s >> Tx >> Ty; // считываем параметры
  648. M = translate(Tx, Ty) * M; // добавляем перенос к общему преобразованию
  649. }
  650. else if (cmd == "scale") { // масштабирование
  651. float S; // параметр масштабирования
  652. s >> S; // считываем параметр
  653. M = scale(S) * M; // добавляем масштабирование к общему преобразованию
  654. }
  655. else if (cmd == "rotate") { // поворот
  656. float theta; // угол поворота в градусах
  657. s >> theta; // считываем параметр
  658. M = rotate(-theta / 180.f * Math::PI) * M; // добавляем поворот к общему преобразованию
  659. }
  660. else if (cmd == "pushTransform") { // сохранение матрицы в стек
  661. transforms.push_back(M); // сохраняем матрицу в стек
  662. }
  663. else if (cmd == "popTransform") { // откат к матрице из стека
  664. M = transforms.back(); // получаем верхний элемент стека
  665. transforms.pop_back(); // выкидываем матрицу из стека
  666. }
  667. }
  668.  
  669. // считываем очередную строку
  670. getline(in, str);
  671. }
  672.  
  673. Refresh();
  674. }
  675. }
  676. }
  677. };
  678. }
  679.  
  680. // MyForm.cpp
  681.  
  682. #include <fstream>
  683. #include <sstream>
  684. #include <vector>
  685. #include "Matrix.h"
  686. #include "Transform.h"
  687. #include "Figure.h"
  688. #include "Clip.h"
  689. #include "MyForm.h"
  690.  
  691. using namespace System;
  692. using namespace System::Windows::Forms;
  693.  
  694. [STAThreadAttribute]
  695. void Main(cli::array<String^>^ args) {
  696. Application::EnableVisualStyles();
  697. Application::SetCompatibleTextRenderingDefault(false);
  698. Moskvitin::MyForm form;
  699. Application::Run(% form);
  700. }
Add Comment
Please, Sign In to add comment