#include "Mesh.hpp" Mesh::Mesh(Object& _obj, double _step) : obj(_obj), step(_step) { for (double y = 0.0; y <= _obj.Height(); y += _step) { mesh.push_back(std::vector()); for (double x = 0.0; x <= _obj.Width(); x += _step) { mesh.back().push_back(new Node(x, y)); } } LinkX(); LinkY(); Adapt(); } void Mesh::VisualizeMesh(std::string name) { std::ofstream data_file(name); data_file << "# Coordinates\n"; data_file << "# Format: x y\n"; for (const auto& row : mesh) { for (const auto& node : row) { data_file << node->X() << " " << node->Y() << "\n"; } } data_file.close(); } void Mesh::LinkX() { for (int i = 0; i < mesh.size(); i++) { mesh[i][0]->LinkX(nullptr, mesh[i][1]); for (int j = 1; j < mesh[i].size() - 1; j++) mesh[i][j]->LinkX(mesh[i][j - 1], mesh[i][j + 1]); mesh[i].back()->LinkX(mesh[i][mesh[i].size() - 2], nullptr); } for (int i = 0; i < mesh.size(); i++) hlines.push_back(mesh[i][0]); } void Mesh::LinkY() { for (int j = 0; j < mesh[0].size(); j++) { mesh[0][j]->LinkY(nullptr, mesh[1][j]); for (int i = 1; i < mesh.size() - 1; i++) mesh[i][j]->LinkY(mesh[i - 1][j], mesh[i + 1][j]); mesh[mesh.size() - 1][j]->LinkY(mesh[mesh.size() - 2][j], nullptr); } for (int i = 0; i < mesh[0].size(); i++) vlines.push_back(mesh[0][i]); } void Mesh::Adapt() { for (int i = 0; i < mesh.size(); i++) { int s = mesh[i].size(); for (int j = 0; j < s; j++) { if (!obj.Inhere(mesh[i][j]->X(), mesh[i][j]->Y())) { Delnode(i, j); j--; s--; } } } } void Mesh::Delnode(int i, int j) { Node* node = mesh[i][j]; /* Вычисляются границы формы по осям X и Y */ double bndX1 = obj.FillX(node->X(), node->Y()).first; double bndX2 = obj.FillX(node->X(), node->Y()).second; double bndY1 = obj.FillY(node->X(), node->Y()).first; double bndY2 = obj.FillY(node->X(), node->Y()).second; /* ГУ формы */ int btype = obj.Who(node->X(), node->Y())->GetB(); if (node->l()) { // Если левый сосед не лежит на границе примитива if (node->l()->X() != bndX2 && node->l()->X() != bndX1) { if (bndX1 != bndX2) { /* Создаем узлы на границах bndX2 и bndX1 с ГУ btype */ Node* left = new Node(bndX2, node->Y(), btype); Node* right = new Node(bndX1, node->Y(), btype); node->l()->r() = left; if (node->r()) node->r()->l() = right; /* Устанавливаем связи для новых узлов по оси X */ left->LinkX(node->l(), right); right->LinkX(left, node->r()); node->l() = right; mesh[i].push_back(left); mesh[i].push_back(right); } /* Если границы по X совпадают, создаем один узел */ else { Node* left = new Node(bndX2, node->Y(), btype); node->l()->r() = left; if (node->r()) node->r()->l() = left; left->LinkX(node->l(), node->r()); node->l() = left; mesh[i].push_back(left); } } /* Если левый сосед уже на границе, связываем его с правым соседом */ else node->l()->r() = node->r(); } /* По аналогии с левым узлом */ if (node->r()) { node->r()->l() = node->l(); } if (node->d()) { if (node->d()->Y() != bndY2 && node->d()->Y() != bndY1) { if (bndY2 != bndY1) { Node* down = new Node(node->X(), bndY2, btype); Node* up = new Node(node->X(), bndY1, btype); node->d()->u() = down; if (node->u()) node->u()->d() = up; down->LinkY(node->d(), up); up->LinkY(down, node->u()); node->d() = up; mesh[i].push_back(down); mesh[i].push_back(up); } else { Node* down = new Node(node->X(), bndY2, btype); node->d()->u() = down; if (node->u()) node->u()->d() = down; down->LinkY(node->d(), node->u()); node->d() = down; mesh[i].push_back(down); } } else node->d()->u() = node->u(); } if (node->u()) { node->u()->d() = node->d(); } mesh[i].erase(mesh[i].begin() + j); delete node; } Mesh::~Mesh() { for (auto line : mesh) for (auto node : line) delete node; }