97 lines
2.6 KiB
C++
97 lines
2.6 KiB
C++
#pragma once
|
|
|
|
#include <list>
|
|
#include <bits/stdc++.h> // For INT_MIN & INT_MAX
|
|
|
|
#include "Point.h"
|
|
#include "Line.h"
|
|
#include "Triangle.h"
|
|
|
|
class Quickhull
|
|
{
|
|
public:
|
|
static void get_hull(std::list<Point> &input, std::list<Point> &output)
|
|
{
|
|
// Get leftmost and rightmost point
|
|
Point leftmost(INT_MAX, 0), rightmost(INT_MIN, 0);
|
|
|
|
for (const Point &point : input)
|
|
{
|
|
if (point.x() < leftmost.x()) {
|
|
leftmost = point;
|
|
} else if (point.y() > rightmost.y()) {
|
|
rightmost = point;
|
|
}
|
|
}
|
|
// Add them to the output
|
|
output.emplace_back(leftmost);
|
|
output.emplace_back(rightmost);
|
|
|
|
// Remove them from the input (as well as duplicates)
|
|
input.remove(leftmost);
|
|
input.remove(rightmost);
|
|
|
|
// Create a line from leftmost to rightmost
|
|
Line line = Line(leftmost, rightmost);
|
|
|
|
// Sort points between left and right of that line
|
|
std::list<Point> points_left, points_right;
|
|
|
|
for (const Point &point : input)
|
|
{
|
|
if (line.is_point_right(point))
|
|
{
|
|
points_right.emplace_back(point);
|
|
}
|
|
else
|
|
{
|
|
points_left.emplace_back(point);
|
|
}
|
|
|
|
}
|
|
|
|
// Call get_hull_with_line with the left points, as well as with the right points, and the line
|
|
get_hull_with_line(points_left, output, line);
|
|
get_hull_with_line(points_right, output, line);
|
|
}
|
|
|
|
private:
|
|
static void get_hull_with_line(std::list<Point> &input, std::list<Point> &output, const Line &line)
|
|
{
|
|
// If the input vector is empty, we're done
|
|
if (input.empty()) return;
|
|
|
|
// Find the point which is furthest away from the line, add it to the output
|
|
Point furthest_point; // TODO
|
|
|
|
output.emplace_back(furthest_point);
|
|
|
|
// Build a triangle with these 3 points
|
|
|
|
// The order with which we must pass the points depends on where the new furthest point is
|
|
Point a, b, c;
|
|
if (line.is_point_right(furthest_point))
|
|
{
|
|
a = line.from();
|
|
b = line.to();
|
|
c = furthest_point;
|
|
}
|
|
else
|
|
{
|
|
a = line.from();
|
|
b = furthest_point;
|
|
c = line.to();
|
|
}
|
|
|
|
Triangle triangle(a, b, c);
|
|
|
|
// Remove points inside this triangle
|
|
input.remove_if([triangle](Point point)
|
|
{
|
|
return !triangle.is_point_inside(point);
|
|
});
|
|
|
|
// Recursively call get_hull_with_line for each side of the triangle
|
|
// TODO
|
|
}
|
|
}; |