diff --git a/cosets/CMakeLists.txt b/cosets/CMakeLists.txt index b2374c3..1a26a91 100644 --- a/cosets/CMakeLists.txt +++ b/cosets/CMakeLists.txt @@ -9,10 +9,7 @@ add_custom_command( add_executable(${PROJECT_NAME} src/main.cpp - src/util/coxeter.cpp src/util/files.cpp - src/util/mesh.cpp - src/util/mirrors.cpp src/util/numeric.cpp src/util/shader.cpp src/util/window.cpp) diff --git a/cosets/include/coxeter.hpp b/cosets/include/coxeter.hpp index 30e6b4c..80e8bce 100644 --- a/cosets/include/coxeter.hpp +++ b/cosets/include/coxeter.hpp @@ -4,90 +4,233 @@ #include #include +template struct Mults; +template struct Table; struct IRow; +template struct Mults { - int num_gens; - std::map, int> mults; + const int dim = NGENS; + std::map, int> mults; - Mults(); + Mults() { + mults = std::map, int>(); + } - void set(int a, int b, int mult); + void set(int a, int b, int mult) { + if (a > b) std::swap(a, b); + mults[std::make_tuple(a, b)] = mult; + } - [[nodiscard]] int get(int a, int b) const; + [[nodiscard]] int get(int a, int b) const { + if (a == b) return 1; + if (a > b) std::swap(a, b); - [[nodiscard]] std::vector relation(int a, int b) const; + const auto &tup = std::make_tuple(a, b); + const auto &res = mults.find(tup); - [[nodiscard]] std::vector> relations(const std::vector &gens) const; + if (res == mults.end()) return 2; + return res->second; + } - [[nodiscard]] std::vector> irelations(const Table *table, const std::vector &gens) const; + [[nodiscard]] std::vector irelation(int a, int b) const { + std::vector res{}; + int mult = get(a, b); - [[nodiscard]] Table *solve(const std::vector &subgens) const; - [[nodiscard]] Table *solve(const std::vector &gens, const std::vector &subgens) const; + for (int i = 0; i < mult; ++i) { + res.push_back(a); + res.push_back(b); + } + + return res; + } + + [[nodiscard]] Table *isolve(const std::vector &isubgens) const; + + template + [[nodiscard]] Table *isolve(const int (&igens)[IGENS], const std::vector &isubgens) const; }; +template struct Table { - const std::vector gens; - const Mults mults; - std::vector gen_inds; - std::vector> fwd; - std::vector> rev; + const Mults mults; + std::vector> fwd; - explicit Table(const std::vector &gens, Mults mults); + explicit Table(Mults mults) : mults(mults) { + add_row(); + } - [[nodiscard]] int gen_index(int gen) const; + void add_row() { + fwd.emplace_back(NGENS, -1); + } - [[nodiscard]] std::vector gen_index_each(std::vector rel) const; + int add_coset() { + for (int from = 0; from < (int) size(); ++from) { + for (int igen = 0; igen < (int) NGENS; igen++) { + if (iget(from, igen) < 0) { + int to = (int) size(); + add_row(); + iset(from, igen, to); + return to; + } + } + } + return 0; + } - void add_row(); + [[nodiscard]] unsigned size() const { + return fwd.size(); + } - int add_coset(); + void iset(int from, int igen, int to) { + fwd[from][igen] = to; + fwd[to][igen] = from; + } - [[nodiscard]] unsigned size() const; + [[nodiscard]] int iget(int from, int igen) const { + return fwd[from][igen]; + } - void set(int from, int gen, int to); + [[nodiscard]] int irget(int igen, int to) const { + return fwd[to][igen]; + } - [[nodiscard]] int get(int from, int gen) const; - - [[nodiscard]] int rget(int gen, int to) const; - - void iset(int from, int igen, int to); - - [[nodiscard]] int iget(int from, int igen) const; - - [[nodiscard]] int irget(int igen, int to) const; - - [[nodiscard]] std::vector> words() const; - - [[nodiscard]] int apply(int e, const std::vector &word) const; - - [[nodiscard]] int apply(const std::vector &word) const; - - [[nodiscard]] std::vector apply_each(int e, const std::vector> &words) const; - - [[nodiscard]] std::vector apply_each(const std::vector> &words) const; }; struct IRow { - std::vector::const_iterator l; - std::vector::const_iterator r; + std::vector::const_iterator l; + std::vector::const_iterator r; - int from; - int to; + int from; + int to; - IRow(const std::vector &rel, int cos); + IRow(const std::vector &rel, int cos) + : l(rel.begin()), r(rel.end() - 1), from(cos), to(cos) { + } - [[nodiscard]] bool learn(Table *table); + template + [[nodiscard]] bool learn(Table *table) { + if (r - l == 0) { + return false; + } + + while (r - l > 0) { + int next = table->iget(from, *l); + if (next < 0) break; + l++; + from = next; + } + + while (r - l > 0) { + int next = table->irget(*r, to); + if (next < 0) break; + r--; + to = next; + } + + if (r - l == 0) { + table->iset(from, *l, to); + return true; + } + + return false; + } }; -//Table *solve(const std::vector &gens, const std::vector &subgens, const Mults &mults); -// -//Table *solve(const std::vector &subgens, const Mults &mults); -// -//Table *solve_elems(const Mults &mults); +template +Mults schlafli(const int(&symbol)[NGENS - 1]) { + Mults mults{}; + for (int i = 0; i < NGENS; ++i) { + mults.set(i, i + 1, symbol[i]); + } + return mults; +} -Mults schlafli(const std::vector &symbol); +template +Table *Mults::isolve(const std::vector &isubgens) const { + auto *table = new Table(*this); + for (int igen : isubgens) + table->iset(0, igen, 0); -std::vector all_gens(int N); + std::vector> irels{}; + for (unsigned a = 0; a < NGENS; ++a) { + for (unsigned b = a + 1; b < NGENS; ++b) { + irels.push_back(irelation(a, b)); + } + } + + std::vector irows; + irows.reserve(irels.size()); + for (const auto &irel : irels) + irows.emplace_back(irel, 0); + + while (!irows.empty()) { + while (true) { + bool learned = false; + for (int i = (int) irows.size() - 1; i >= 0; i--) { + if (irows[i].learn(table)) { + learned = true; + irows.erase(irows.begin() + i); + } + } + if (!learned) + break; + } + + int i = (int) table->size(); + if (table->add_coset() > 0) { + for (const auto &irel : irels) + irows.emplace_back(irel, i); + } else { + break; + } + } + + return table; +} + +template +template +Table *Mults::isolve(const int (&igens)[IGENS], const std::vector &isubgens) const { + auto *table = new Table(*this); + for (int igen : isubgens) + table->iset(0, igen, 0); + + std::vector> irels{}; + for (unsigned a = 0; a < igens.size(); ++a) { + for (unsigned b = a + 1; b < igens.size(); ++b) { + irels.push_back(irelation(igens[a], igens[b])); + } + } + + std::vector irows; + irows.reserve(irels.size()); + for (const auto &irel : irels) + irows.emplace_back(irel, 0); + + while (!irows.empty()) { + while (true) { + bool learned = false; + for (int i = (int) irows.size() - 1; i >= 0; i--) { + if (irows[i].learn(table)) { + learned = true; + irows.erase(irows.begin() + i); + } + } + if (!learned) + break; + } + + int i = (int) table->size(); + if (table->add_coset() > 0) { + for (const auto &irel : irels) + irows.emplace_back(irel, i); + } else { + break; + } + } + + return table; +} diff --git a/cosets/include/mesh.hpp b/cosets/include/mesh.hpp index 08ea46e..9bc8c80 100644 --- a/cosets/include/mesh.hpp +++ b/cosets/include/mesh.hpp @@ -1,43 +1,112 @@ #pragma once #include +#include +#include #include "coxeter.hpp" #include "mirrors.hpp" #include "numeric.hpp" -glm::vec4 identity(const std::vector &normals, const std::vector &coords); +glm::vec4 identity(const std::vector &normals, const std::vector &coords) { + const std::vector corners = plane_intersections(normals); + const glm::vec4 identity = barycentric(corners, coords); + return glm::normalize(identity); +} -glm::vec4 identity(const Mults &mults, const std::vector &coords); -glm::vec4 center(const Mults &mults); +template +glm::vec4 identity(const Mults &mults, const std::vector &coords) { + const std::vector normals = mirror(mults); + return identity(normals, coords); +} -std::vector vertices(const Table *t_vert, const glm::vec4 ident); -std::vector edges(const Table *t_vert); - -std::vector faces(const Table *t_vert); +template +glm::vec4 center(const Mults &mults) { + const std::vector normals = mirror(mults); + const std::vector corners = plane_intersections(normals); + std::vector coords{}; + for (int i = 0; i < corners.size(); ++i) { + const auto u = (i + 2) % corners.size(); + const auto v = (i + 1) % corners.size(); + const auto &d = corners[u] - corners[v]; + coords.push_back(glm::length(d)); + } + const glm::vec4 identity = barycentric(corners, coords); + return glm::normalize(identity); +} struct Buffer { - const GLuint name; - const unsigned size; - const float gen_time; + GLuint name = 0; + unsigned size = 0; }; +template struct Mesh { - const Mults mults; - const Table *t_vert; + const Mults mults; + const Table *t_vert; - Buffer vert; - Buffer edge; - Buffer face; + const std::vector normals; + glm::vec4 *vert_data; - Mesh(Mults mults, const Table *t_vert, Buffer vert, Buffer edge, Buffer face); + Buffer vert; + Buffer edge; + Buffer face; - ~Mesh(); + explicit Mesh(Mults mults) : mults(mults), normals(mirror(mults)) { + auto a = std::chrono::high_resolution_clock::now(); + t_vert = mults.isolve({}); + auto b = std::chrono::high_resolution_clock::now(); + std::cout << "time to solve: " << ((std::chrono::duration) (b - a)).count() << std::endl; + + vert.size = t_vert->size(); + vert_data = new glm::vec4[vert.size]; + + glGenBuffers(1, &vert.name); + glGenBuffers(1, &edge.name); + glGenBuffers(1, &face.name); + + gen_indices(); + } + + explicit Mesh(Mults mults, const glm::vec4 root) { + this(mults); + gen_vertices(root); + } + + void gen_vertices(const glm::vec4 root) { + vert_data[0] = root; + for (unsigned from = 0; from < vert.size; ++from) { + for (unsigned gen = 0; gen < NGENS; ++gen) { + int to = t_vert->iget((int) from, (int) gen); + vert_data[to] = reflect(vert_data[from], normals[gen]); + } + } + + glBindBuffer(GL_ARRAY_BUFFER, vert.name); + glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4) * vert.size, vert_data, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + void gen_indices() { + std::vector edges; + std::vector faces; + + glBindBuffer(GL_ARRAY_BUFFER, edge.name); +// glBufferData(GL_ARRAY_BUFFER, sizeof(int) * edge.size, edge_data, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + ~Mesh() { + delete t_vert; + delete[] vert_data; + + glDeleteBuffers(1, &vert.name); + glDeleteBuffers(1, &edge.name); + glDeleteBuffers(1, &face.name); + } }; -Mesh *mesh(const Mults &mults, glm::vec4 ident); - std::ostream &operator<<(std::ostream &out, Buffer b); diff --git a/cosets/include/mirrors.hpp b/cosets/include/mirrors.hpp index e26d574..929f24c 100644 --- a/cosets/include/mirrors.hpp +++ b/cosets/include/mirrors.hpp @@ -2,6 +2,31 @@ #include #include -#include "coxeter.hpp" +#include -std::vector mirror(const Mults &mults); +#include "coxeter.hpp" +#include "numeric.hpp" + +template +std::vector mirror(const Mults &mults) { + std::vector mirrors{}; + for (int p = 0; p < NGENS; ++p) { + glm::vec4 vp{}; + for (int m = 0; m < p; ++m) { + glm::vec4 vq = mirrors[m]; + vp[m] = (cos(M_PI / mults.get(p, m)) - dot(m, vp, vq)) / vq[m]; + } + vp[p] = std::sqrt(1 - glm::dot(vp, vp)); + + for (const auto &v : mirrors) { + if (glm::dot(vp, v) > 0) { + vp *= -1; + break; + } + } + + mirrors.push_back(round(vp, 15)); + } + + return mirrors; +} diff --git a/cosets/src/main.cpp b/cosets/src/main.cpp index 7d00ee1..7d0aa88 100644 --- a/cosets/src/main.cpp +++ b/cosets/src/main.cpp @@ -13,149 +13,152 @@ using namespace std; class CosetsWindow : public Window { - GLint program; - GLuint vert_vao, edge_vao, face_vao; + GLint program; + GLuint vert_vao, edge_vao, face_vao; - Mesh *figure; + Mesh<4> *figure; - GLint u_proj, u_view, u_color; + GLint u_proj, u_view, u_color; public: - void init() override { - std::cout - << "Graphics Information:" << std::endl - << "Vendor: " << glGetString(GL_VENDOR) << std::endl - << "Renderer: " << glGetString(GL_RENDERER) << std::endl - << "Version: " << glGetString(GL_VERSION) << std::endl - << "Shading version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; + void init() override { + std::cout + << "Graphics Information:" << std::endl + << "Vendor: " << glGetString(GL_VENDOR) << std::endl + << "Renderer: " << glGetString(GL_RENDERER) << std::endl + << "Version: " << glGetString(GL_VERSION) << std::endl + << "Shading version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; - auto vs = build_shader_file( - GL_VERTEX_SHADER, - "vertex", - "shaders/main.vs.glsl"); + auto vs = build_shader_file( + GL_VERTEX_SHADER, + "vertex", + "shaders/main.vs.glsl"); - auto fs = build_shader_file( - GL_FRAGMENT_SHADER, - "fragment", - "shaders/main.fs.glsl"); + auto fs = build_shader_file( + GL_FRAGMENT_SHADER, + "fragment", + "shaders/main.fs.glsl"); - program = build_program("main", vs, fs); + program = build_program("main", vs, fs); - u_proj = glGetUniformLocation(program, "proj"); - u_view = glGetUniformLocation(program, "view"); - u_color = glGetUniformLocation(program, "color"); + u_proj = glGetUniformLocation(program, "proj"); + u_view = glGetUniformLocation(program, "view"); + u_color = glGetUniformLocation(program, "color"); - const Mults &mults = schlafli({5, 3, 2}); -// const glm::vec4 ident = center(mults); - const glm::vec4 ident = identity(mults, {2, .1, .1, 3}); - std::cout << "Dimension: " << mults.num_gens << std::endl; + figure = new Mesh(schlafli<4>({5, 3, 3})); - figure = mesh(mults, ident); + glGenVertexArrays(1, &vert_vao); + glBindVertexArray(vert_vao); + glBindBuffer(GL_ARRAY_BUFFER, figure->vert.name); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr); + glBindBuffer(GL_ARRAY_BUFFER, 0); - glGenVertexArrays(1, &vert_vao); - glBindVertexArray(vert_vao); - glBindBuffer(GL_ARRAY_BUFFER, figure->vert.name); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glGenVertexArrays(1, &edge_vao); + glBindVertexArray(edge_vao); + glBindBuffer(GL_ARRAY_BUFFER, figure->vert.name); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, figure->edge.name); - glGenVertexArrays(1, &edge_vao); - glBindVertexArray(edge_vao); - glBindBuffer(GL_ARRAY_BUFFER, figure->vert.name); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, figure->edge.name); + glGenVertexArrays(1, &face_vao); + glBindVertexArray(face_vao); + glBindBuffer(GL_ARRAY_BUFFER, figure->vert.name); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, figure->face.name); - glGenVertexArrays(1, &face_vao); - glBindVertexArray(face_vao); - glBindBuffer(GL_ARRAY_BUFFER, figure->vert.name); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, figure->face.name); + glBindVertexArray(0); + } - glBindVertexArray(0); - } + void render() override { + int w, h; + getBounds(w, h); + glViewport(0, 0, w, h); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - void render() override { - int w, h; - getBounds(w, h); - glViewport(0, 0, w, h); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + const auto id = glm::mat4(1); + const auto ax_1 = glm::vec3(0, 0, 1); + const auto ax_2 = glm::vec3(.5, 1, 0.2); + const auto t = glfwGetTime(); + const auto angle = (float) t / 3; - const auto id = glm::mat4(1); - const auto ax_1 = glm::vec3(0, 0, 1); - const auto ax_2 = glm::vec3(.5, 1, 0.2); - const auto t = glfwGetTime(); - const auto angle = (float) t / 5; + const float sc = 1.5f; + const float ar = (float) w / (float) h; - const float sc = 1.5f; - const float ar = (float) w / (float) h; + const float c1 = std::cos(angle * 3.0); + const float s1 = std::sin(angle * 3.0); + const float c2 = std::cos(angle * 0.2); + const float s2 = std::sin(angle * 0.2); - const float c1 = std::cos(angle * .7); - const float s1 = std::sin(angle * .7); - const float c2 = std::cos(angle * .5); - const float s2 = std::sin(angle * .5); + const glm::mat4 proj = glm::ortho(-ar * sc, ar * sc, -sc, sc, -10.f, 10.f); + const glm::mat4 view = glm::rotate(id, angle, ax_1) * glm::rotate(id, angle, ax_2) + * glm::mat4( + c1, 0.0, s1, 0.0, + 0.0, c2, 0.0, s2, + -s1, 0.0, c1, 0.0, + 0.0, -s2, 0.0, c2 + ); - const glm::mat4 proj = glm::ortho(-ar * sc, ar * sc, -sc, sc, -10.f, 10.f); - const glm::mat4 view = glm::rotate(id, angle, ax_1) * glm::rotate(id, angle, ax_2) - * glm::mat4( - c1, 0.0, s1, 0.0, - 0.0, c2, 0.0, s2, - -s1, 0.0, c1, 0.0, - 0.0, -s2, 0.0, c2 - ); + const float root_x = std::cos((t + 0) * M_PI / 2) / 2 + 0.5; + const float root_y = std::cos((t + 1) * M_PI / 2) / 2 + 0.5; + const float root_z = std::cos((t + 2) * M_PI / 2) / 2 + 0.5; + const float root_w = std::cos((t + 3) * M_PI / 2) / 2 + 0.5; - glUseProgram(program); - glUniformMatrix4fv(u_proj, 1, false, glm::value_ptr(proj)); - glUniformMatrix4fv(u_view, 1, false, glm::value_ptr(view)); + const glm::vec4 root = identity<4>(figure->mults, {root_x, root_y, root_z, root_w}); + figure->gen_vertices(root); - glEnable(GL_DEPTH_TEST); - glEnable(GL_POINT_SMOOTH); - glEnable(GL_BLEND); - glEnable(GL_CULL_FACE); + glUseProgram(program); + glUniformMatrix4fv(u_proj, 1, false, glm::value_ptr(proj)); + glUniformMatrix4fv(u_view, 1, false, glm::value_ptr(view)); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_DEPTH_TEST); + glEnable(GL_POINT_SMOOTH); + glEnable(GL_BLEND); + glEnable(GL_CULL_FACE); - glPointSize(10.0f); - glLineWidth(5.0f); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindVertexArray(vert_vao); - glUniform4f(u_color, 1, 0, 0, 1); - glDrawArrays(GL_POINTS, 0, figure->vert.size); + glPointSize(10.0f); + glLineWidth(5.0f); - glBindVertexArray(edge_vao); - glUniform4f(u_color, 1, 0, 0, 1); - glDrawElements(GL_LINES, figure->edge.size, GL_UNSIGNED_INT, 0); + glBindVertexArray(vert_vao); + glUniform4f(u_color, 1, 0, 0, 1); + glDrawArrays(GL_POINTS, 0, figure->vert.size); - glBindVertexArray(face_vao); - glCullFace(GL_NONE); - glUniform4f(u_color, 1, 1, 1, 1); + glBindVertexArray(edge_vao); + glUniform4f(u_color, 1, 0, 0, 1); + glDrawElements(GL_LINES, figure->edge.size, GL_UNSIGNED_INT, 0); + +// glBindVertexArray(face_vao); +// glCullFace(GL_NONE); +// glUniform4f(u_color, 1, 1, 1, 1); // glDrawElements(GL_TRIANGLES, figure->face.size, GL_UNSIGNED_INT, 0); // glCullFace(GL_FRONT); // glUniform4f(u_color, .3, .3, 1, 1); // glDrawElements(GL_TRIANGLES, figure->face.size, GL_UNSIGNED_INT, 0); - swapbuffers(); - } + swapbuffers(); + } - void deinit() override { - glDeleteProgram(program); - glDeleteVertexArrays(1, &vert_vao); - } + void deinit() override { + glDeleteProgram(program); + glDeleteVertexArrays(1, &vert_vao); + } }; int main(int argc, char *argv[]) { - if (!glfwInit()) { - fprintf(stderr, "Failed to initialize GLFW\n"); - return EXIT_FAILURE; - } + if (!glfwInit()) { + fprintf(stderr, "Failed to initialize GLFW\n"); + return EXIT_FAILURE; + } - Window *window = new CosetsWindow(); - window->run(); + Window *window = new CosetsWindow(); + window->run(); - glfwTerminate(); - return EXIT_SUCCESS; + glfwTerminate(); + return EXIT_SUCCESS; } diff --git a/cosets/src/util/coxeter.cpp b/cosets/src/util/coxeter.cpp deleted file mode 100644 index dd1b928..0000000 --- a/cosets/src/util/coxeter.cpp +++ /dev/null @@ -1,281 +0,0 @@ -#include "coxeter.hpp" - -Mults::Mults() { - num_gens = 0; - mults = std::map, int>(); -} - -void Mults::set(int a, int b, int mult) { - if (a > b) std::swap(a, b); - if (b + 1 > num_gens) num_gens = b + 1; - mults[std::make_tuple(a, b)] = mult; -} - -int Mults::get(int a, int b) const { - if (a == b) return 1; - if (a > b) std::swap(a, b); - - const auto &tup = std::make_tuple(a, b); - const auto &res = mults.find(tup); - - if (res == mults.end()) return 2; - return res->second; -} - -std::vector Mults::relation(int a, int b) const { - std::vector res{}; - int mult = get(a, b); - - for (int i = 0; i < mult; ++i) { - res.push_back(a); - res.push_back(b); - } - - return res; -} - -std::vector> Mults::relations(const std::vector &gens) const { - std::vector> res{}; - for (int a = 0; a < (int) gens.size(); ++a) { - for (int b = a; b < (int) gens.size(); ++b) { - res.push_back(relation(gens[a], gens[b])); - } - } - return res; -} - -std::vector> Mults::irelations(const Table *table, const std::vector &gens) const { - std::vector> rels = relations(gens); - std::vector> irels(rels.size()); - for (int i = 0; i < (int) rels.size(); ++i) { - irels[i] = table->gen_index_each(rels[i]); - } - return irels; -} - -Table::Table(const std::vector &gens, const Mults mults) : gens(gens), mults(mults) { - add_row(); - - gen_inds = std::vector(gens[gens.size() - 1] + 1, -1); - for (int i = 0; i < (int) gens.size(); i++) { - gen_inds[gens[i]] = i; - } -} - -int Table::gen_index(int gen) const { - if (gen >= gen_inds.size()) - throw std::logic_error("Referencing nonexistant generator (too large)"); - int i = gen_inds[gen]; - if (i < 0) - throw std::logic_error("Referencing nonexistant generator (not present)"); - return i; -} - -std::vector Table::gen_index_each(std::vector rel) const { - std::vector res(rel.size(), 0); - for (int i = 0; i < (int) rel.size(); ++i) { - res[i] = gen_index(rel[i]); - } - return res; -} - -void Table::add_row() { - int N = gens.size(); - fwd.emplace_back(N, -1); - rev.emplace_back(N, -1); -} - -int Table::add_coset() { - for (int from = 0; from < (int) size(); ++from) { - for (int igen = 0; igen < (int) gens.size(); igen++) { - if (iget(from, igen) < 0) { - int to = (int) size(); - add_row(); - iset(from, igen, to); - return to; - } - } - } - return 0; -} - -unsigned Table::size() const { - return fwd.size(); -} - -void Table::set(int from, int gen, int to) { - int i = gen_index(gen); - fwd[from][i] = to; - rev[to][i] = from; -} - -int Table::get(int from, int gen) const { - int i = gen_index(gen); - return fwd[from][i]; -} - -int Table::rget(int gen, int to) const { - int i = gen_index(gen); - return rev[to][i]; -} - -void Table::iset(int from, int igen, int to) { - fwd[from][igen] = to; - rev[to][igen] = from; -} - -int Table::iget(int from, int igen) const { - return fwd[from][igen]; -} - -int Table::irget(int igen, int to) const { - return rev[to][igen]; -} - -std::vector> Table::words() const { - std::vector *> vecs(size()); - vecs[0] = new std::vector(); - - while (std::find(vecs.begin(), vecs.end(), nullptr) != vecs.end()) { - for (int from = 0; from < (int) vecs.size(); ++from) { - std::vector *word = vecs[from]; - if (word == nullptr) { - continue; - } - - for (int igen = 0; igen < gens.size(); igen++) { - int to = iget(from, igen); - if (vecs[to] != nullptr) { - continue; - } - - vecs[to] = new std::vector(*word); - vecs[to]->push_back(gens[igen]); - } - } - } - - std::vector> res(size()); - for (int i = 0; i < (int) size(); ++i) { - res[i] = *vecs[i]; - delete vecs[i]; - } - - return res; -} - -int Table::apply(int e, const std::vector &word) const { - for (const auto &gen : word) { - e = get(e, gen); - } - return e; -} - -int Table::apply(const std::vector &word) const { - return apply(0, word); -} - -std::vector Table::apply_each(int e, const std::vector> &words) const { - std::vector res{}; - - for (const auto &word:words) { - res.push_back(apply(e, word)); - } - - return res; -} - -std::vector Table::apply_each(const std::vector> &words) const { - return apply_each(0, words); -} - -IRow::IRow(const std::vector &rel, int cos) { - this->l = rel.begin(); - this->r = rel.end() - 1; - this->from = cos; - this->to = cos; -} - -bool IRow::learn(Table *table) { - if (r - l == 0) { - return false; - } - - while (r - l > 0) { - int next = table->iget(from, *l); - if (next < 0) break; - l++; - from = next; - } - - while (r - l > 0) { - int next = table->irget(*r, to); - if (next < 0) break; - r--; - to = next; - } - - if (r - l == 0) { - table->iset(from, *l, to); - return true; - } - - return false; -} - -Table *Mults::solve(const std::vector &gens, const std::vector &subgens) const { - auto *table = new Table(gens, *this); - const auto irels = irelations(table, gens); - - for (int gen : subgens) - table->set(0, gen, 0); - - std::vector irows; - irows.reserve(irels.size()); - for (const auto &irel : irels) - irows.emplace_back(irel, 0); - - while (!irows.empty()) { - while (true) { - bool learned = false; - for (int i = (int) irows.size() - 1; i >= 0; i--) { - if (irows[i].learn(table)) { - learned = true; - irows.erase(irows.begin() + i); - } - } - if (!learned) - break; - } - - int i = (int) table->size(); - if (table->add_coset() > 0) { - for (const auto &irel : irels) - irows.emplace_back(irel, i); - } else { - break; - } - } - - return table; -} - -Table *Mults::solve(const std::vector &subgens) const { - return this->solve(all_gens(num_gens), subgens); -} - -Mults schlafli(const std::vector &symbol) { - Mults mults{}; - for (int i = 0; i < symbol.size(); ++i) { - mults.set(i, i + 1, symbol[i]); - } - return mults; -} - -std::vector all_gens(int N) { - std::vector gens(N); - for (int i = 0; i < N; ++i) { - gens[i] = i; - } - return gens; -} diff --git a/cosets/src/util/mesh.cpp b/cosets/src/util/mesh.cpp deleted file mode 100644 index 5b3c7da..0000000 --- a/cosets/src/util/mesh.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include - -#include -#include -#include "mesh.hpp" - -glm::vec4 identity(const std::vector &normals, const std::vector &coords) { - const std::vector corners = plane_intersections(normals); - const glm::vec4 identity = barycentric(corners, coords); - return glm::normalize(identity); -} - -glm::vec4 identity(const Mults &mults, const std::vector &coords) { - const std::vector normals = mirror(mults); - return identity(normals, coords); -} - -glm::vec4 center(const Mults &mults) { - const std::vector normals = mirror(mults); - const std::vector corners = plane_intersections(normals); - std::vector coords{}; - for (int i = 0; i < corners.size(); ++i) { - const auto u = (i + 2) % corners.size(); - const auto v = (i + 1) % corners.size(); - const auto &d = corners[u] - corners[v]; - coords.push_back(glm::length(d)); - } - const glm::vec4 identity = barycentric(corners, coords); - return glm::normalize(identity); -} - -Mesh::Mesh(Mults mults, const Table *t_vert, Buffer vert, Buffer edge, Buffer face) - : mults(std::move(mults)), t_vert(t_vert), vert(vert), edge(edge), face(face) { -} - -Mesh::~Mesh() { - delete t_vert; - - glDeleteBuffers(1, &vert.name); - glDeleteBuffers(1, &edge.name); - glDeleteBuffers(1, &face.name); -} - -Mesh *mesh(const Mults &mults, glm::vec4 ident) { - GLuint buffers[3]; - glGenBuffers(3, buffers); - - Table *t_vert = mults.solve({}); - - auto vert_data = vertices(t_vert, ident); - glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4) * vert_data.size(), &vert_data[0], GL_STATIC_DRAW); - Buffer vert{buffers[0], vert_data.size()}; - - auto edge_data = edges(t_vert); - glBindBuffer(GL_ARRAY_BUFFER, buffers[1]); - glBufferData(GL_ARRAY_BUFFER, sizeof(int) * edge_data.size(), &edge_data[0], GL_STATIC_DRAW); - Buffer edge{buffers[1], edge_data.size()}; - - auto face_data = faces(t_vert); - glBindBuffer(GL_ARRAY_BUFFER, buffers[2]); - glBufferData(GL_ARRAY_BUFFER, sizeof(int) * face_data.size(), &face_data[0], GL_STATIC_DRAW); - Buffer face{buffers[2], face_data.size()}; - - return new Mesh(mults, t_vert, vert, edge, face); -} - -std::vector -vertices(const Table *t_vert, const glm::vec4 ident) { - const std::vector normals = mirror(t_vert->mults); - - std::vector verts{}; - for (const auto &word : t_vert->words()) { - glm::vec4 vert = ident; - for (const auto &gen : word) { - vert = reflect(vert, normals[gen]); - } - verts.push_back(vert); - } - - return verts; -} - -std::vector edges(const Table *t_vert) { - std::vector res{}; - - Mults mults = t_vert->mults; - int N = mults.num_gens; - const std::vector &gens = t_vert->gens; - - for (const auto &subgens : combinations(N, 1)) { - Table *t_edge = mults.solve(subgens, {});; - - std::vector edge = t_vert->apply_each(t_edge->words()); - - Table *c_edge = mults.solve(gens, subgens); - - for (const auto &coset : c_edge->words()) { - for (const auto &e : edge) { - res.push_back(t_vert->apply(e, coset)); - } - } - - delete t_edge; - delete c_edge; - } - - return res; -} - -std::vector faces(const Table *t_vert) { - std::vector res{}; - const Mults &mults = t_vert->mults; - int N = mults.num_gens; - const std::vector &gens = t_vert->gens; - - // for each *kind* of face - for (const auto &sg_face : combinations(N, 2)) { - Table *cs_face = mults.solve(gens, sg_face); - - // for each *kind* of edge - for (const auto &sg_edge : combinations(sg_face, 1)) { - Table *cs_edge = mults.solve(sg_face, sg_edge); - - // find the vertices of that edge - Table *t_edge = mults.solve(sg_edge, {}); - std::vector edge = t_vert->apply_each(t_edge->words()); - - // for each face - for (const auto &c_face : cs_face->words()) { - // for each edge - for (const auto &c_edge : cs_edge->words()) { - if (c_edge.empty()) { continue; } - - for (auto e : edge) { - e = t_vert->apply(e, c_edge); - e = t_vert->apply(e, c_face); - res.push_back(e); - } - res.push_back(t_vert->apply(0, c_face)); - - if (c_edge.size() & 1u) - std::swap(res[res.size() - 1], res[res.size() - 2]); - - unsigned ro_si1 = (sg_face[0] + sg_face[1]); - unsigned flag = sg_edge[0] == sg_face[0]; - unsigned n_mirrors = c_face.size(); - - if ((n_mirrors + flag + ro_si1) & 1u) { - std::swap(res[res.size() - 1], res[res.size() - 2]); - } - } - } - - delete t_edge; - delete cs_edge; - } - - delete cs_face; - } - - return res; -} diff --git a/cosets/src/util/mirrors.cpp b/cosets/src/util/mirrors.cpp deleted file mode 100644 index 201143d..0000000 --- a/cosets/src/util/mirrors.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "mirrors.hpp" - -#include -#include "numeric.hpp" -#include "coxeter.hpp" - -std::vector mirror(const Mults &mults) { - int N = mults.num_gens; - - std::vector mirrors{}; - for (int p = 0; p < N; ++p) { - glm::vec4 vp{}; - for (int m = 0; m < p; ++m) { - glm::vec4 vq = mirrors[m]; - vp[m] = (cos(M_PI / mults.get(p, m)) - dot(m, vp, vq)) / vq[m]; - } - vp[p] = std::sqrt(1 - glm::dot(vp, vp)); - - for (const auto &v : mirrors) { - if (glm::dot(vp, v) > 0) { - vp *= -1; - break; - } - } - - mirrors.push_back(round(vp, 15)); - } - - return mirrors; -}