-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcomposable_hulls.hpp
110 lines (96 loc) · 2.91 KB
/
composable_hulls.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#ifndef composable_hulls_hpp
#define composable_hulls_hpp
#include <vector>
#include <string>
#include <utility>
#include <omp.h>
#include <math.h>
#include <sstream>
#include "convex_hull_base.hpp"
#include "graham_scan_parallel.hpp"
#include "jarvis_march_parallel.hpp"
#include "point.hpp"
#include "vector2d.hpp"
namespace csce
{
template<typename T, typename U = graham_scan<T>, typename V = jarvis_march_parallel<T>>
class composable_hulls : public csce::convex_hull_base<T>
{
public:
composable_hulls(int _nthreads) : convex_hull_base<T>(_nthreads) {}
~composable_hulls() {}
std::string name() const
{
return std::string("Composable Hulls <").append(U(0).name()).append(", ").append(V(0).name()).append(">");
}
virtual std::vector<csce::point<T>> compute_hull(std::vector<csce::point<T>> &points)
{
std::vector<std::vector<csce::point<T>>> sectors(this->nthreads);
std::vector<std::vector<csce::point<T>>> hulls(this->nthreads);
double secSize = M_PI / this->nthreads;
size_t topMostPoint = 0;
#pragma omp parallel num_threads(this->nthreads)
{
std::vector<std::vector<csce::point<T>>> localSectors(this->nthreads);
// find top-most point
#pragma omp for
for(size_t i = 0; i < points.size(); i++)
{
if(points[i].y > points[topMostPoint].y)
{
topMostPoint = i;
}
}
// split points up by sector
#pragma omp for
for(size_t i = 0; i < points.size(); i++)
{
double theta = atan2(points[topMostPoint].y - points[i].y, points[topMostPoint].x - points[i].x);
if(theta < 0)
{
if(theta + 1e-3 > 0)
theta = 1e-9;
else
theta = M_PI - 1e-9;
}
size_t sector = theta / secSize;
localSectors[sector].push_back(points[i]);
}
#pragma omp critical
for(size_t i = 0; i < this->nthreads; i++)
sectors[i].insert(sectors[i].end(), localSectors[i].begin(), localSectors[i].end());
#pragma omp barrier
// local convex hull
size_t id = omp_get_thread_num();
if(sectors[id].size() > 2)
hulls[id] = U(1).compute_hull(sectors[id]);
else
hulls[id] = sectors[id]; // not actually a hull, but the points may be in the final hull
}
// composition of local hulls
std::vector<csce::point<T>> resultsOfShortestPath = hulls[0];
V combiner(this->nthreads);
for(size_t i = 1; i < this->nthreads; i++)
{
if(hulls[i].size() > 0)
{
resultsOfShortestPath.insert(resultsOfShortestPath.end(), hulls[i].begin(), hulls[i].end());
resultsOfShortestPath = combiner.compute_hull(resultsOfShortestPath);
}
}
return resultsOfShortestPath;
}
private:
int operation(csce::point<T> d, csce::point<T> e, csce::point<T> f) const
{
int resultsofSin = (e.y - d.y) * (f.x - e.x) - (e.x - d.x) * (f.y - e.y);
if(resultsofSin == 0)
return 0;
else if(resultsofSin > 0)
return 1;
else
return 2;
}
};
}
#endif