Skip to content

Commit c9f38f5

Browse files
committed
Separate convex hull algorithm in a header
1 parent bdc6456 commit c9f38f5

File tree

8 files changed

+144
-114
lines changed

8 files changed

+144
-114
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@
3030
*.exe
3131
*.out
3232
*.app
33+
build/

CMakeLists.txt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
3+
project(DSA)
4+
5+
set(CMAKE_CXX_STANDARD 17)
6+
7+
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$<CONFIG>")
8+
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$<CONFIG>")
9+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$<CONFIG>")
10+
11+
add_subdirectory(geometry)

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@
126126

127127
## 6. [geometry](geometry)
128128

129-
- [convex hull](geometry/convex_hull.cpp)
129+
- [types](geometry/types.h)
130+
- [convex hull](geometry/convex_hull.h)
130131

131132
---
132133

geometry/CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
3+
project(Geometry)
4+
5+
add_executable(main main.cpp)

geometry/convex_hull.cpp

-113
This file was deleted.

geometry/convex_hull.h

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#pragma once
2+
3+
#include "types.h"
4+
5+
#include <vector>
6+
#include <algorithm>
7+
#include <cmath>
8+
9+
namespace geometry
10+
{
11+
[[nodiscard]] static inline std::vector<ivec2>
12+
convex_hull_construct(std::vector<ivec2> points)
13+
{
14+
// lowest y-coordinate and leftmost point
15+
ivec2 pivot = *std::min_element(points.begin(), points.end());
16+
17+
std::sort(
18+
points.begin(),
19+
points.end(),
20+
[&pivot](const ivec2& a, const ivec2& b)
21+
{
22+
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;
25+
}
26+
);
27+
28+
std::vector<ivec2> polygon;
29+
polygon.reserve(points.size());
30+
31+
for (size_t i = 0; i < points.size(); ++i)
32+
{
33+
while (polygon.size() >= 2)
34+
{
35+
auto a = polygon.end()[-2];
36+
auto b = polygon.end()[-1];
37+
auto& c = points[i];
38+
39+
if ((b - a) * (c - a) > 0)
40+
break;
41+
42+
// remove last point if it results in a clockwise orientation or if the points are collinear
43+
polygon.pop_back();
44+
}
45+
polygon.push_back(points[i]);
46+
}
47+
48+
polygon.shrink_to_fit();
49+
return polygon;
50+
}
51+
}

geometry/main.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include "convex_hull.h"
2+
3+
// Problem statement: https://open.kattis.com/problems/convexhull
4+
int main()
5+
{
6+
std::ios_base::sync_with_stdio(false);
7+
std::cin.tie(nullptr);
8+
9+
std::vector<ivec2> points;
10+
points.reserve(10'000 + 9);
11+
12+
int n{};
13+
while (std::cin >> n && n)
14+
{
15+
points.resize(n);
16+
for (size_t i = 0; i < n; ++i)
17+
std::cin >> points[i];
18+
19+
auto polygon = geometry::convex_hull_construct(points);
20+
if (polygon.size() == 2 && polygon[0] == polygon[1])
21+
polygon.pop_back();
22+
23+
std::cout << polygon.size() << '\n';
24+
for (size_t i = 0; i < polygon.size(); ++i)
25+
std::cout << polygon[i] << '\n';
26+
}
27+
}

geometry/types.h

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#pragma once
2+
3+
#include <iostream>
4+
5+
struct ivec2
6+
{
7+
int64_t x, y;
8+
9+
inline bool operator<(const ivec2& other) const
10+
{
11+
return (y != other.y) ? (y < other.y) : (x < other.x);
12+
}
13+
14+
inline bool operator==(const ivec2& other) const
15+
{
16+
return (x == other.x) && (y == other.y);
17+
}
18+
19+
inline ivec2 operator-(const ivec2& other) const
20+
{
21+
return ivec2{x - other.x, y - other.y};
22+
}
23+
24+
inline ivec2& operator-=(const ivec2& other)
25+
{
26+
x -= other.x;
27+
y -= other.y;
28+
return *this;
29+
}
30+
31+
inline int64_t operator*(const ivec2& other) const
32+
{
33+
return x * other.y - y * other.x;
34+
}
35+
};
36+
37+
std::ostream& operator<<(std::ostream& out, const ivec2& vec)
38+
{
39+
out << vec.x << " " << vec.y;
40+
return out;
41+
}
42+
43+
std::istream& operator>>(std::istream& in, ivec2& vec)
44+
{
45+
in >> vec.x >> vec.y;
46+
return in;
47+
}

0 commit comments

Comments
 (0)