Skip to content

Commit 4b84f12

Browse files
committed
Add Boolean for strictly_convex construction
1 parent c9f38f5 commit 4b84f12

File tree

4 files changed

+30
-10
lines changed

4 files changed

+30
-10
lines changed

geometry/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 3.16)
22

33
project(Geometry)
44

5-
add_executable(main main.cpp)
5+
add_executable(geometry geometry.cpp)

geometry/convex_hull.h

+24-7
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
#include <vector>
66
#include <algorithm>
7-
#include <cmath>
87

98
namespace geometry
109
{
1110
[[nodiscard]] static inline std::vector<ivec2>
12-
convex_hull_construct(std::vector<ivec2> points)
11+
convex_hull_construct(std::vector<ivec2> points, bool strictly_convex = true)
1312
{
1413
// lowest y-coordinate and leftmost point
1514
ivec2 pivot = *std::min_element(points.begin(), points.end());
@@ -20,11 +19,27 @@ namespace geometry
2019
[&pivot](const ivec2& a, const ivec2& b)
2120
{
2221
auto area = (a - pivot) * (b - pivot);
23-
auto a_smaller = ::abs(pivot.x - a.x) + ::abs(pivot.y - a.y) < ::abs(pivot.x - b.x) + ::abs(pivot.y - b.y);
24-
return (area != 0) * (area > 0) + (area == 0) * a_smaller;
22+
if (area == 0)
23+
{
24+
auto pivot_a = a - pivot;
25+
auto pivot_b = b - pivot;
26+
return pivot_a.dot(pivot_a) < pivot_b.dot(pivot_b);
27+
}
28+
else
29+
{
30+
return area > 0;
31+
}
2532
}
2633
);
2734

35+
if (!strictly_convex)
36+
{
37+
int reverse_index = (int)points.size() - 2;
38+
while (reverse_index > 0 && (points.back() - pivot) * (points[reverse_index] - pivot) == 0)
39+
reverse_index--;
40+
std::reverse(points.begin() + reverse_index + 1, points.end());
41+
}
42+
2843
std::vector<ivec2> polygon;
2944
polygon.reserve(points.size());
3045

@@ -34,9 +49,8 @@ namespace geometry
3449
{
3550
auto a = polygon.end()[-2];
3651
auto b = polygon.end()[-1];
37-
auto& c = points[i];
38-
39-
if ((b - a) * (c - a) > 0)
52+
auto area = (b - a) * (points[i] - a);
53+
if (area > 0 || (area == 0 && !strictly_convex))
4054
break;
4155

4256
// remove last point if it results in a clockwise orientation or if the points are collinear
@@ -45,6 +59,9 @@ namespace geometry
4559
polygon.push_back(points[i]);
4660
}
4761

62+
if (strictly_convex && polygon.size() == 2 && polygon[0] == polygon[1])
63+
polygon.pop_back();
64+
4865
polygon.shrink_to_fit();
4966
return polygon;
5067
}

geometry/main.cpp renamed to geometry/geometry.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ int main()
1717
std::cin >> points[i];
1818

1919
auto polygon = geometry::convex_hull_construct(points);
20-
if (polygon.size() == 2 && polygon[0] == polygon[1])
21-
polygon.pop_back();
2220

2321
std::cout << polygon.size() << '\n';
2422
for (size_t i = 0; i < polygon.size(); ++i)

geometry/types.h

+5
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ struct ivec2
3232
{
3333
return x * other.y - y * other.x;
3434
}
35+
36+
inline int64_t dot(const ivec2& other) const
37+
{
38+
return x * other.x + y * other.y;
39+
}
3540
};
3641

3742
std::ostream& operator<<(std::ostream& out, const ivec2& vec)

0 commit comments

Comments
 (0)