168 lines
4.7 KiB
C++
168 lines
4.7 KiB
C++
/*
|
|
* <Short Description>
|
|
* 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "blt/std/logging.h"
|
|
#include <shifting.h>
|
|
#include <blt/math/vectors.h>
|
|
#include <vector>
|
|
#include <blt/std/hashmap.h>
|
|
|
|
inline constexpr char from_char(char c)
|
|
{
|
|
return c;
|
|
}
|
|
|
|
struct vertex_data
|
|
{
|
|
char name;
|
|
HASHSET<char> neighbours;
|
|
blt::vec2 pos;
|
|
|
|
vertex_data(char name, const HASHSET<char>& 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<vertex_data> edges = {
|
|
vertex_data{'a', HASHSET<char>{'i', 'e', 'b', 'j', 'h'}},
|
|
vertex_data{'b', HASHSET<char>{'a', 'e', 'c', 'j'}},
|
|
vertex_data{'c', HASHSET<char>{'e', 'd', 'f', 'j', 'b'}},
|
|
vertex_data{'d', HASHSET<char>{'e', 'f', 'c'}},
|
|
vertex_data{'e', HASHSET<char>{'h', 'f', 'd', 'c', 'b', 'a', 'i'}},
|
|
vertex_data{'f', HASHSET<char>{'d', 'e', 'h', 'g', 'j', 'c'}},
|
|
vertex_data{'g', HASHSET<char>{'j', 'f', 'h'}},
|
|
vertex_data{'h', HASHSET<char>{'j', 'g', 'f', 'e', 'i', 'a'}},
|
|
vertex_data{'i', HASHSET<char>{'e', 'a', 'h'}},
|
|
vertex_data{'j', HASHSET<char>{'a', 'b', 'c', 'f', 'g', 'h'}},
|
|
};
|
|
|
|
HASHSET<char>& 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<char> 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<vertex_data> 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())
|
|
{
|
|
|
|
}
|
|
}
|