Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quickhull #3

Merged
merged 2 commits into from
Oct 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions quickHull.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include "quickHull.hpp"
#include "utils.hpp"
#include <cmath>
#define max_y 1000000000
#define min_y -1000000000
// Output hull
std::vector<Point> convex_hull;

void quickHull(Point p, Point q, std::vector<Point> points)
{
if (points.size() > 0)
{
Point farthest;
long double max_dist = 0;

// Select the point at maximum distance from line
for (Point point : points)
{
long double dist = point.findDist(p, q);
if (dist > max_dist)
{
max_dist = dist;
farthest = point;
}
}
// Select points outside triangle formed by p, q, farthest
std::vector<Point> upper, lower;
for (Point point : points)
{
if (signedTriangleArea(farthest, p, point) > 0)
{
upper.push_back(point);
}
if (signedTriangleArea(q, farthest, point) > 0)
{
lower.push_back(point);
}
}
// Recurse on exterior points afer pruning interior points
quickHull(farthest, p, upper);
// Add farthest point from line pq to convex hull
convex_hull.push_back(farthest);
quickHull(q, farthest, lower);
}
}

std::vector<Point> Hull(std::vector<Point> points)
{
if (points.size() <= 2)
{
return points;
}

// Select top-most and bottom-most point
Point p , q;
p.x = q.x = 0;
p.y = min_y;
q.y = max_y;
for (Point point : points)
{
if (point.y < q.y)
{
q = point;
}
else if (point.y == q.y && point.x > q.x)
{
q = point;
}
if (point.y > p.y)
{
p = point;
}
else if (point.y == p.y && point.x > p.x)
{
p = point;
}
}

// Split into two sets, left and right of the line joining q to p.
std::vector<Point> left, right;
for (Point point : points)
{
if (signedTriangleArea(p, q, point) < 0)
{
left.push_back(point);
}
else if (signedTriangleArea(p, q, point) > 0)
{
right.push_back(point);
}
}
// Add p to the convex hull
convex_hull.push_back(p);
quickHull(p, q, left);
// Add q to the convex hull
convex_hull.push_back(q);
quickHull(q, p, right);

return convex_hull;
}
16 changes: 16 additions & 0 deletions quickHull.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/** @file */

#pragma once
#include "utils.hpp"
#include <vector>

/**
* Return the Convex Hull of a set of points using the Quickhull algorithm.
* Works in worse case time complexity O(N*N) and space complexity O(N+H) where N is the number of points and H is the number of points in the Convex Hull.
*
* @param points A vector of points for which the Convex Hull is to be found
* @return A vector of points which contains the points of the Convex Hull
*
* @relatesalso Point
*/
std::vector<Point> Hull(std::vector<Point> points);
3 changes: 2 additions & 1 deletion test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "utils.hpp"
#include "grahamScan.hpp"
#include "jarvisMarch.hpp"
#include "quickHull.hpp"
#include <iostream>

int main()
Expand All @@ -15,7 +16,7 @@ int main()
points.push_back(Point(x, y));
}

std::vector<Point> ch = jarvisMarch(points);
std::vector<Point> ch = Hull(points);

for (Point p : ch)
{
Expand Down
11 changes: 9 additions & 2 deletions utils.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "utils.hpp"

#include <cmath>
Point::Point(long double x, long double y) : y(y), x(x) {}
Point::Point() : y(0), x(0) {}
bool Point::operator==(const Point &point)
{
return (x == point.x && y == point.y);
Expand All @@ -9,4 +10,10 @@ bool Point::operator==(const Point &point)
long double signedTriangleArea(Point A, Point B, Point C)
{
return 0.5 * ((B.x - A.x) * (C.y - A.y) - (C.x - A.x) * (B.y - A.y));
}
}

long double Point::findDist(Point p, Point q)
{
return std :: abs ((y - p.y) * (q.x - p.x) -
(q.y - p.y) * (x - p.x));
}
11 changes: 10 additions & 1 deletion utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Point
* Equality operator. Two points are equal if they have the same x and y coordinates
*/
bool operator==(const Point &point);
long double findDist(Point p, Point q);
};

/**
Expand All @@ -42,4 +43,12 @@ class Point
*
* @relatesalso Point
*/
long double signedTriangleArea(Point A, Point B, Point C);
long double signedTriangleArea(Point A, Point B, Point C);
/**
* Find distance of a point from a line joining two points.
* @param p 1st Point
* @param q 2nd Point
* @return The distance of Point from the line joining p and q.
*
* @relatesalso Point
*/