/* * * Copyright (C) 2024 Brett Terpstra * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "blt/std/logging.h" #include #include #include #include inline constexpr char from_char(char c) { return c; } struct vertex_data { char name; HASHSET neighbours; blt::vec2 pos; vertex_data(char name, const HASHSET& n): name(from_char(name)) { for (const auto& v : n) neighbours.insert(from_char(v)); } vertex_data(char name, const blt::vec2& pos): name(from_char(name)), pos(pos) {} }; using Point = const blt::vec2&; bool onSegment(Point p, Point q, Point r) { if (q.x() <= std::max(p.x(), r.x()) && q.x() >= std::min(p.x(), r.x()) && q.y() <= std::max(p.y(), r.y()) && q.y() >= std::min(p.y(), r.y())) return true; return false; } int orientation(Point p, Point q, Point r) { // for details of below formula. int val = (q.y() - p.y()) * (r.x() - q.x()) - (q.x() - p.x()) * (r.y() - q.y()); if (val == 0) return 0; // collinear return (val > 0) ? 1 : 2; // clock or counterclock wise } bool doIntersect(Point p1, Point q1, Point p2, Point q2) { // Find the four orientations needed for general and // special cases int o1 = orientation(p1, q1, p2); int o2 = orientation(p1, q1, q2); int o3 = orientation(p2, q2, p1); int o4 = orientation(p2, q2, q1); // General case if (o1 != o2 && o3 != o4) return true; // Special Cases // p1, q1 and p2 are collinear and p2 lies on segment p1q1 if (o1 == 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on segment p1q1 if (o2 == 0 && onSegment(p1, q2, q1)) return true; // p2, q2 and p1 are collinear and p1 lies on segment p2q2 if (o3 == 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on segment p2q2 if (o4 == 0 && onSegment(p2, q1, q2)) return true; return false; // Doesn't fall in any of the above cases } float ccw(const blt::vec2& A, const blt::vec2& B, const blt::vec2& C) { return (C.y() - A.y()) * (B.x() - A.x()) > (B.y() - A.y()) * (C.x() - A.x()); } // Return true if line segments AB and CD intersect bool intersects(const blt::vec2& A, const blt::vec2& B, const blt::vec2& C, const blt::vec2& D) { return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D); } std::vector edges = { vertex_data{'a', HASHSET{'i', 'e', 'b', 'j', 'h'}}, vertex_data{'b', HASHSET{'a', 'e', 'c', 'j'}}, vertex_data{'c', HASHSET{'e', 'd', 'f', 'j', 'b'}}, vertex_data{'d', HASHSET{'e', 'f', 'c'}}, vertex_data{'e', HASHSET{'h', 'f', 'd', 'c', 'b', 'a', 'i'}}, vertex_data{'f', HASHSET{'d', 'e', 'h', 'g', 'j', 'c'}}, vertex_data{'g', HASHSET{'j', 'f', 'h'}}, vertex_data{'h', HASHSET{'j', 'g', 'f', 'e', 'i', 'a'}}, vertex_data{'i', HASHSET{'e', 'a', 'h'}}, vertex_data{'j', HASHSET{'a', 'b', 'c', 'f', 'g', 'h'}}, }; HASHSET& getEdges(char c) { for (auto& e : edges) if (e.name == c) return e.neighbours; BLT_FATAL("Failed to find character in edge set"); std::exit(2); } std::vector order = { from_char('f'), from_char('d'), from_char('c'), from_char('g'), from_char('j'), from_char('b'), from_char('e'), from_char('i'), from_char('a'), from_char('h'), }; std::vector out; bool has_intersection(Point p, char c) { return false; } void shift_right(int units) { } void calculate_ordering() { out.push_back(vertex_data{order.back(), blt::vec2{0, 0}}); out.back().neighbours = getEdges(out.back().name); order.pop_back(); out.push_back(vertex_data{order.back(), blt::vec2{2, 0}}); out.back().neighbours = getEdges(out.back().name); order.pop_back(); while (!order.empty()) { } }