#pragma once namespace Guschin { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace std; vec2 Vc; vec2 V; vec2 Vc_work, V_work; mat3 T; mat3 initT; public ref class MyForm : public System::Windows::Forms::Form { public: MyForm(void) { InitializeComponent(); } protected: ~MyForm() { if (components) { delete components; } } private: System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code void InitializeComponent(void) { this->SuspendLayout(); // // MyForm // this->AutoScaleDimensions = System::Drawing::SizeF(8, 16); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(737, 686); this->KeyPreview = true; this->Margin = System::Windows::Forms::Padding(4, 4, 4, 4); this->Name = L"MyForm"; this->Text = L"MyForm"; this->Load += gcnew System::EventHandler(this, &MyForm::MyForm_Load); this->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &MyForm::MyForm_Paint); this->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &MyForm::MyForm_KeyDown); this->Resize += gcnew System::EventHandler(this, &MyForm::MyForm_Resize); this->ResumeLayout(false); } #pragma endregion private: float left = 30, right = 100, top = 20, bottom = 50; float minX = left, maxX; float minY = top, maxY; float Wcx = left, Wcy; float Wx, Wy; private: System::Void rectCalc() { maxX = ClientRectangle.Width - right; maxY = ClientRectangle.Height - bottom; Wcy = maxY; Wx = maxX - left; Wy = maxY - top; } System::Void worldRectCalc() { Vc_work = normalize(T * vec3(Vc, 1.f)); V_work = mat2(T) * V; } float f(float x) { return tan(x); } bool f_exists(float x, float delta) { return fabs(2.f * acos(cos(x)) - Math::PI) > delta; } private: System::Void MyForm_Resize(System::Object^ sender, System::EventArgs^ e) { rectCalc(); Refresh(); } private: System::Void MyForm_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) { Graphics^ g = e->Graphics; g->Clear(Color::Aquamarine); Pen^ rectPen = gcnew Pen(Color::Black, 2); g->DrawRectangle(rectPen, left, top, Wx, Wy); Pen^ pen = gcnew Pen(Color::Blue, 1); float deltaX = V_work.x / Wx; bool hasStart, hasEnd; vec2 start, end; float x, y; start.x = Wcx; x = Vc_work.x; hasStart = f_exists(x, deltaX); if (hasStart) { y = f(x); start.y = Wcy - (y - Vc_work.y) / V_work.y * Wy; } while (start.x < maxX) { end.x = start.x + 1.f; x += deltaX; hasEnd = f_exists(x, deltaX); if (hasEnd) { y = f(x); end.y = Wcy - (y - Vc_work.y) / V_work.y * Wy; } vec2 tmpEnd = end; bool visible = hasStart && hasEnd && clip(start, end, minX, minY, maxX, maxY); if (visible) { g->DrawLine(pen, start.x, start.y, end.x, end.y); } start = tmpEnd; hasStart = hasEnd; } } private: System::Void MyForm_Load(System::Object^ sender, System::EventArgs^ e) { initT = mat3(1.f); T = initT; Vc = vec2(-2.f, -2.f); V = vec2(4.f, 4.f); rectCalc(); worldRectCalc(); } private: System::Void MyForm_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e) { float centerX = Vc_work.x + V_work.x / 2; float centerY = Vc_work.y + V_work.y / 2; switch (e->KeyCode) { case Keys::Escape: T = initT; break; case Keys::A: T = translate(-V_work.x / Wx, 0.f) * T; break; case Keys::Z: T = translate(-centerX, -centerY) * T; T = scale(1.1) * T; T = translate(centerX, centerY) * T; break; default: break; } worldRectCalc(); Refresh(); } }; }