Thu, 15 Jun 2023 16:18:03 +0300
Refactor, make selecting elements from the model select the corresponding line from the editor as well
#pragma once #include <glm/gtc/matrix_transform.hpp> #include "src/basics.h" #include "src/model.h" #include "src/ldrawalgorithm.h" template<typename Fn> void circular_element_to_polygons(const circular_primitive& circ, Fn&& fn) { std::vector<ModelElement> result; const auto xform = [&circ](const glm::vec2& p, float y){ return glm::vec3{circ.transformation * glm::vec4{p.x, y, p.y, 1}}; }; const glm::vec3 primitiveOrigin = xform({0, 0}, 0); const bool invertedMatrix = (glm::determinant(circ.transformation) < 0) != circ.inverted; switch(circ.type) { case circular_primitive_type_e::circle: ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ fn(LineSegment{xform(p1, 0), xform(p2, 0)}, EDGE_COLOR); }); break; case circular_primitive_type_e::disc: ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ fn(Triangle{primitiveOrigin, xform(p1, 0), xform(p2, 0)}, MAIN_COLOR); }); break; case circular_primitive_type_e::cylinder: ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ Quadrilateral quad{xform(p1, 1), xform(p2, 1), xform(p2, 0), xform(p1, 0)}; if (invertedMatrix) { std::swap(quad.p2, quad.p4); } fn(quad, MAIN_COLOR); }); break; case circular_primitive_type_e::cylinder_open: circular_element_to_polygons(circular_primitive{ .type = circular_primitive_type_e::cylinder, .fraction = circ.fraction, .transformation = circ.transformation, }, fn); circular_element_to_polygons(circular_primitive{ .type = circular_primitive_type_e::circle, .fraction = circ.fraction, .transformation = circ.transformation, }, fn); circular_element_to_polygons(circular_primitive{ .type = circular_primitive_type_e::circle, .fraction = circ.fraction, .transformation = glm::translate(circ.transformation, {0, 1, 0}), }, fn); break; case circular_primitive_type_e::cylinder_closed: circular_element_to_polygons(circular_primitive{ .type = circular_primitive_type_e::cylinder_open, .fraction = circ.fraction, .transformation = circ.transformation, }, fn); circular_element_to_polygons(circular_primitive{ .type = circular_primitive_type_e::disc, .fraction = circ.fraction, .transformation = circ.transformation, }, fn); break; case circular_primitive_type_e::disc_negative: { unsigned int i = 0; ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&] (const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){ constexpr glm::vec2 corners[4] = { {+1, +1}, {-1, +1}, {-1, -1}, {+1, -1}, }; const glm::vec2& corner = corners[i * 4 / circ.fraction.divisions]; fn(Triangle{xform(p2, 0), xform(p1, 0), xform(corner, 0)}, MAIN_COLOR); ++i; }); } break; case circular_primitive_type_e::chord: for (unsigned int i = 1; i < circ.fraction.segments; ++i) { const glm::vec2& p1 = ldraw::rimpoint(circ.fraction.divisions, i); const glm::vec2& p2 = ldraw::rimpoint(circ.fraction.divisions, i + 1); fn(Triangle{xform(p2, 0), xform(p1, 0), xform({1, 0}, 0)}, MAIN_COLOR); } break; } }