Tvor0zhok

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

Mar 21st, 2022 (edited)
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.08 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.  
  201. class path
  202. {
  203. public:
  204.  
  205. std::vector <vec2> vertices; // последовательность точек
  206. vec3 color; // цвет, разбитый на составляющие RGB
  207. float thickness; // толщина линии
  208.  
  209. path(std::vector <vec2> verts, vec3 col, float thickn)
  210. {
  211. vertices = verts;
  212. color = col;
  213. thickness = thickn;
  214. }
  215. };
  216.  
  217. // MyForm.h
  218.  
  219. #pragma once
  220.  
  221. namespace Moskvitin {
  222.  
  223. using namespace System;
  224. using namespace System::ComponentModel;
  225. using namespace System::Collections;
  226. using namespace System::Windows::Forms;
  227. using namespace System::Data;
  228. using namespace System::Drawing;
  229. using namespace std;
  230.  
  231. mat3 T = mat3(1.f); // матрица, в которой накапливаются все преобразования
  232. mat3 initT; // матрица начального преобразования
  233.  
  234. vector <path> figure;
  235.  
  236. float Vx, Vy; // размеры рисунка по горизонтали и вертикали
  237. float aspectFig; // соотношение сторон рисунка
  238.  
  239. /// <summary>
  240. /// Сводка для MyForm
  241. /// </summary>
  242. public ref class MyForm : public System::Windows::Forms::Form
  243. {
  244. public:
  245. MyForm(void)
  246. {
  247. InitializeComponent();
  248. //
  249. //TODO: добавьте код конструктора
  250. //
  251. }
  252.  
  253. protected:
  254. /// <summary>
  255. /// Освободить все используемые ресурсы.
  256. /// </summary>
  257. ~MyForm()
  258. {
  259. if (components)
  260. {
  261. delete components;
  262. }
  263. }
  264. private: System::Windows::Forms::OpenFileDialog^ openFileDialog;
  265. protected:
  266. private: System::Windows::Forms::Button^ btnOpen;
  267.  
  268. private:
  269. /// <summary>
  270. /// Обязательная переменная конструктора.
  271. /// </summary>
  272. System::ComponentModel::Container ^components;
  273.  
  274. #pragma region Windows Form Designer generated code
  275. /// <summary>
  276. /// Требуемый метод для поддержки конструктора — не изменяйте
  277. /// содержимое этого метода с помощью редактора кода.
  278. /// </summary>
  279. void InitializeComponent(void)
  280. {
  281. this->openFileDialog = (gcnew System::Windows::Forms::OpenFileDialog());
  282. this->btnOpen = (gcnew System::Windows::Forms::Button());
  283. this->SuspendLayout();
  284. //
  285. // openFileDialog
  286. //
  287. this->openFileDialog->DefaultExt = L"txt";
  288. this->openFileDialog->Filter = L"Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)|*.*";
  289. this->openFileDialog->Title = L"Открыть файл";
  290. //
  291. // btnOpen
  292. //
  293. this->btnOpen->Location = System::Drawing::Point(178, 12);
  294. this->btnOpen->Name = L"btnOpen";
  295. this->btnOpen->Size = System::Drawing::Size(88, 31);
  296. this->btnOpen->TabIndex = 0;
  297. this->btnOpen->Text = L"Открыть";
  298. this->btnOpen->UseVisualStyleBackColor = true;
  299. this->btnOpen->Click += gcnew System::EventHandler(this, &MyForm::btnOpen_Click);
  300. //
  301. // MyForm
  302. //
  303. this->AutoScaleDimensions = System::Drawing::SizeF(9, 20);
  304. this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
  305. this->ClientSize = System::Drawing::Size(278, 244);
  306. this->Controls->Add(this->btnOpen);
  307. this->KeyPreview = true;
  308. this->Name = L"MyForm";
  309. this->Text = L"MyForm";
  310. this->Load += gcnew System::EventHandler(this, &MyForm::MyForm_Load);
  311. this->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &MyForm::MyForm_Paint);
  312. this->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &MyForm::MyForm_KeyDown);
  313. this->Resize += gcnew System::EventHandler(this, &MyForm::MyForm_Resize);
  314. this->ResumeLayout(false);
  315.  
  316. }
  317. #pragma endregion
  318. private: System::Void MyForm_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) {
  319. // описываем переменную g - область рисования, ссылку на объект типа System::Drawing::Graphics^
  320. Graphics^ g = e->Graphics;
  321. g->Clear(Color::White);
  322.  
  323. for (int i = 0; i < figure.size(); ++i)
  324. {
  325. path lines = figure[i]; // очередная ломаная линия
  326. Pen^ pen = gcnew Pen(Color::FromArgb(lines.color.x, lines.color.y, lines.color.z));
  327. pen->Width = lines.thickness;
  328.  
  329. vec2 start = normalize(T * vec3(lines.vertices[0], 1.0)); // 1-ая начальная точка
  330.  
  331. for (int j = 1; j < lines.vertices.size(); ++j)
  332. {
  333. vec2 end = normalize(T * vec3(lines.vertices[j], 1.0)); // конечная точка
  334. g->DrawLine(pen, start.x, start.y, end.x, end.y);
  335.  
  336. start = end; // конечная точка текущего отрезка становится начальной точкой следующего
  337. }
  338. }
  339. }
  340.  
  341. private: System::Void MyForm_Resize(System::Object^ sender, System::EventArgs^ e) {
  342. // Добавляем устойчивость рисунка относительно изменения размера окна
  343. Refresh();
  344. }
  345.  
  346. private: System::Void MyForm_Load(System::Object^ sender, System::EventArgs^ e) {
  347. }
  348.  
  349. private: System::Void MyForm_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e) {
  350. // координаты центров
  351. float Wcx = ClientRectangle.Width / 2.f; // по ширине
  352. float Wcy = ClientRectangle.Height / 2.f; // по высоте
  353.  
  354. switch (e->KeyCode)
  355. {
  356. // поворот на 0.01 радиан против часовой стрелки
  357. case Keys::Q:
  358. T = translate(-Wcx, -Wcy) * T; // перенос начала координат в (Wcx, Wcy)
  359. T = rotate(0.01f) * T; // поворот
  360. T = translate(Wcx, Wcy) * T; // перенос начала координат обратно
  361. break;
  362. // сдвиг изображения вверх на 1 пиксель
  363. case Keys::W:
  364. T = translate(0.f, -1.f) * T;
  365. break;
  366. // сброс всех преобразований
  367. case Keys::Escape:
  368. T = initT;
  369. break;
  370. // поворот на 0.01 радиан по часовой стрелке
  371. case Keys::E:
  372. T = translate(-Wcx, -Wcy) * T; // перенос начала координат в (Wcx, Wcy)
  373. T = rotate(-0.01f) * T; // поворот
  374. T = translate(Wcx, Wcy) * T; // перенос начала координат обратно
  375. break;
  376. // сдвиг изображения вниз на 1 пиксель
  377. case Keys::S:
  378. T = translate(0.f, 1.f) * T;
  379. break;
  380. // сдвиг изображения влево на 1 пиксель
  381. case Keys::A:
  382. T = translate(-1.f, 0.f) * T;
  383. break;
  384. // сдвиг изображения вправо на 1 пиксель
  385. case Keys::D:
  386. T = translate(1.f, 0.f) * T;
  387. break;
  388. // поворот на 0.05 радиан по часовой стрелке
  389. case Keys::R:
  390. T = translate(-Wcx, -Wcy) * T;
  391. T = rotate(-0.05f) * T;
  392. T = translate(Wcx, Wcy) * T;
  393. break;
  394. // поворот на 0.05 радиан против часовой стрелки
  395. case Keys::Y:
  396. T = translate(-Wcx, -Wcy) * T;
  397. T = rotate(0.05f) * T;
  398. T = translate(Wcx, Wcy) * T;
  399. break;
  400. // сдвиг изображения вверх на 10 пикселей
  401. case Keys::T:
  402. T = translate(0.f, -10.f) * T;
  403. break;
  404. // сдвиг изображения вниз на 10 пикселей
  405. case Keys::G:
  406. T = translate(0.f, 10.f) * T;
  407. break;
  408. // сдвиг изображения влево на 10 пикселей
  409. case Keys::F:
  410. T = translate(-10.f, 0.f) * T;
  411. break;
  412. // сдвиг изображения вправо на 10 пикселей
  413. case Keys::H:
  414. T = translate(10.f, 0.f) * T;
  415. break;
  416. // увеличение изображения в 1.1 раз
  417. case Keys::Z:
  418. T = translate(-Wcx, -Wcy) * T;
  419. T = scale(1.1f) * T;
  420. T = translate(Wcx, Wcy) * T;
  421. break;
  422. // уменьшение изображения в 1.1 раз
  423. case Keys::X:
  424. T = translate(-Wcx, -Wcy) * T;
  425. T = scale(10.f / 11.f) * T;
  426. T = translate(Wcx, Wcy) * T;
  427. break;
  428. // зеркальное отражения относительно горизонтальной оси, проходящей через центр окна
  429. case Keys::U:
  430. T = translate(-Wcx, -Wcy) * T;
  431. T = mirrorX() * T;
  432. T = translate(Wcx, Wcy) * T;
  433. break;
  434. // зеркальное отражение относительно вертикальной оси, проходящей через центр окна
  435. case Keys::J:
  436. T = translate(-Wcx, -Wcy) * T;
  437. T = mirrorY() * T;
  438. T = translate(Wcx, Wcy) * T;
  439. break;
  440. // растяжение изображения по горизонтали в 1.1 раз
  441. case Keys::I:
  442. T = translate(-Wcx, -Wcy) * T;
  443. T = scale(1.1f, 1.f) * T;
  444. T = translate(Wcx, Wcy) * T;
  445. break;
  446. // сжатие изображения по горизонтали в 1.1 раз
  447. case Keys::K:
  448. T = translate(-Wcx, -Wcy) * T;
  449. T = scale(10.f / 11.f, 1.f) * T;
  450. T = translate(Wcx, Wcy) * T;
  451. break;
  452. // растяжение изображения по вертикали в 1.1 раз
  453. case Keys::O:
  454. T = translate(-Wcx, -Wcy) * T;
  455. T = scale(1.f, 1.1f) * T;
  456. T = translate(Wcx, Wcy) * T;
  457. break;
  458. // сжатие изображения по вертикали в 1.1 раз
  459. case Keys::L:
  460. T = translate(-Wcx, -Wcy) * T;
  461. T = scale(1.f, 10.f / 11.f) * T;
  462. T = translate(Wcx, Wcy) * T;
  463. break;
  464. default:break;
  465. }
  466.  
  467. Refresh();
  468. }
  469. private: System::Void btnOpen_Click(System::Object^ sender, System::EventArgs^ e) {
  470. if (openFileDialog->ShowDialog() == System::Windows::Forms::DialogResult::OK)
  471. {
  472. // в файловом диалоге нажата кнопка OK
  473.  
  474. // перезапись имени файла из openFileDialog->FileName в fileName
  475. wchar_t fileName[1024]; // переменная, в которой посимвольно сохраним имя файла
  476.  
  477. for (int i = 0; i < openFileDialog->FileName->Length; i++)
  478. fileName[i] = openFileDialog->FileName[i];
  479.  
  480. fileName[openFileDialog->FileName->Length] = '\0';
  481.  
  482. // объявление и открытие файла
  483.  
  484. ifstream in;
  485. in.open(fileName);
  486.  
  487. if (in.is_open())
  488. {
  489. // файл успешно открыт
  490.  
  491. figure.clear(); // очищаем имеющийся список ломаных
  492.  
  493. // временные переменные для чтения из файла
  494. float thickness = 2; // толщина со значением по умолчанию 2
  495. float r, g, b; // составляющие цвета
  496. r = g = b = 0; // значение составляющих цвета по умолчанию (черный)
  497.  
  498. // непосредственно работа с файлом
  499.  
  500. string str; // строка, в которую считываем строки файла
  501. getline(in, str); // считываем из входного файла первую строку
  502. while (in) // если очередная строка считана успешно
  503. {
  504. // обрабатываем строку
  505. if ((str.find_first_not_of(" \t\r\n") != string::npos) && (str[0] != '#'))
  506. {
  507. // прочитанная строка не пуста и не комментарий
  508. stringstream s(str); // строковый поток из строки str
  509.  
  510. string cmd; // переменная для имени команды
  511. s >> cmd; // считываем имя команды
  512.  
  513. if (cmd == "frame") { // размеры изображения
  514. s >> Vx >> Vy; // считываем глобальные значение Vx и Vy
  515. aspectFig = Vx / Vy; // обновление соотношения сторон
  516.  
  517. // размеры окна
  518. float Wx = ClientRectangle.Width; // ширина окна
  519. float Wy = ClientRectangle.Height; // высота окна
  520.  
  521. // соотношение сторон окна рисования
  522. float aspectForm = Wx / Wy;
  523.  
  524. // коэффициент увеличения при сохранении исходного соотношения сторон
  525. float S = aspectFig < aspectForm ? Wy / Vy : Wx / Vx;
  526.  
  527. float Ty = S * Vy; // смещение в положительную сторону по оси Oy после смены знака
  528.  
  529. initT = translate(0.f, Ty) * scale(S, -S); // масштабирование и перенос
  530.  
  531. T = initT;
  532. }
  533. else if (cmd == "color") { // цвет линии
  534. s >> r >> g >> b; // считываем три составляющие цвета
  535. }
  536. else if (cmd == "thickness") { // толщина линии
  537. s >> thickness; // считываем значение толщины
  538. }
  539. else if (cmd == "path") { // набор точек
  540. vector<vec2> vertices; // список точек ломаной
  541.  
  542. int N; // количество точек
  543. s >> N;
  544.  
  545. string str1; // дополнительная строка для чтения из файла
  546.  
  547. while (N > 0) { // пока не все точки считали
  548. getline(in, str1); // считываем в str1 из входного файла очередную строку
  549. // так как файл корректный, то на конец файла проверять не нужно
  550.  
  551. if ((str1.find_first_not_of(" \t\r\n") != string::npos) && (str1[0] != '#')) {
  552. // прочитанная строка не пуста и не комментарий
  553. // значит в ней пара координат
  554.  
  555. float x, y; // переменные для считывания
  556. stringstream s1(str1); // еще один строковый поток из строки str1
  557. s1 >> x >> y;
  558. vertices.push_back(vec2(x, y)); // добавляем точку в список
  559. N--; // уменьшаем счетчик после успешного считывания точки
  560. }
  561. }
  562. // все точки считаны, генерируем ломаную (path) и кладем ее в список figure
  563. figure.push_back(path(vertices, vec3(r, g, b), thickness));
  564. }
  565. }
  566.  
  567. // считываем очередную строку
  568. getline(in, str);
  569. }
  570.  
  571. Refresh();
  572. }
  573. }
  574. }
  575. };
  576. }
  577.  
  578. // MyForm.cpp
  579.  
  580. #include <fstream>
  581. #include <sstream>
  582. #include <vector>
  583. #include "Matrix.h"
  584. #include "Transform.h"
  585. #include "Figure.h"
  586. #include "Clip.h"
  587. #include "MyForm.h"
  588.  
  589. using namespace System;
  590. using namespace System::Windows::Forms;
  591.  
  592. [STAThreadAttribute]
  593. void Main(cli::array<String^>^ args) {
  594. Application::EnableVisualStyles();
  595. Application::SetCompatibleTextRenderingDefault(false);
  596. Moskvitin::MyForm form;
  597. Application::Run(% form);
  598. }
Add Comment
Please, Sign In to add comment