-
Notifications
You must be signed in to change notification settings - Fork 93
Expand file tree
/
Copy path3D hull.cpp
More file actions
82 lines (77 loc) · 2.47 KB
/
3D hull.cpp
File metadata and controls
82 lines (77 loc) · 2.47 KB
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
template<class T> struct Point3D {
typedef Point3D P;
typedef const P& R;
T x, y, z;
explicit Point3D(T x=0, T y=0, T z=0) : x(x), y(y), z(z) {}
bool operator<(R p) const {
return tie(x, y, z) < tie(p.x, p.y, p.z); }
bool operator==(R p) const {
return tie(x, y, z) == tie(p.x, p.y, p.z); }
P operator+(R p) const { return P(x+p.x, y+p.y, z+p.z); }
P operator-(R p) const { return P(x-p.x, y-p.y, z-p.z); }
P operator*(T d) const { return P(x*d, y*d, z*d); }
P operator/(T d) const { return P(x/d, y/d, z/d); }
T dot(R p) const { return x*p.x + y*p.y + z*p.z; }
P cross(R p) const {
return P(y*p.z - z*p.y, z*p.x - x*p.z, x*p.y - y*p.x);
}
T dist2() const { return x*x + y*y + z*z; }
double dist() const { return sqrt((double)dist2()); }
//Azimuthal angle (longitude) to x-axis in interval [-pi, pi]
double phi() const { return atan2(y, x); }
//Zenith angle (latitude) to the z-axis in interval [0, pi]
double theta() const { return atan2(sqrt(x*x+y*y),z); }
P unit() const { return *this/(T)dist(); } //makes dist()=1
//returns unit vector normal to *this and p
P normal(P p) const { return cross(p).unit(); }
//returns point rotated 'angle' radians ccw around axis
P rotate(double angle, P axis) const {
double s = sin(angle), c = cos(angle); P u = axis.unit();
return u*dot(u)*(1-c) + (*this)*c - cross(u)*s;
}
};
typedef Point3D<double> P3;
struct PR {
void ins(int x) { (a == -1 ? a : b) = x; }
void rem(int x) { (a == x ? a : b) = -1; }
int cnt() { return (a != -1) + (b != -1); }
int a, b;
};
struct F { P3 q; int a, b, c; };
vector<F> hull3d(const vector<P3>& A) {
assert(sz(A) >= 4);
vector<vector<PR>> E(sz(A), vector<PR>(sz(A), {-1, -1}));
#define E(x,y) E[f.x][f.y]
vector<F> FS;
auto mf = [&](int i, int j, int k, int l) {
P3 q = (A[j] - A[i]).cross((A[k] - A[i]));
if (q.dot(A[l]) > q.dot(A[i]))
q = q * -1;
F f{q, i, j, k};
E(a,b).ins(k); E(a,c).ins(j); E(b,c).ins(i);
FS.push_back(f);
};
rep(i,0,4) rep(j,i+1,4) rep(k,j+1,4)
mf(i, j, k, 6 - i - j - k);
rep(i,4,sz(A)) {
rep(j,0,sz(FS)) {
F f = FS[j];
if(f.q.dot(A[i]) > f.q.dot(A[f.a])) {
E(a,b).rem(f.c);
E(a,c).rem(f.b);
E(b,c).rem(f.a);
swap(FS[j--], FS.back());
FS.pop_back();
}
}
int nw = sz(FS);
rep(j,0,nw) {
F f = FS[j];
#define C(a, b, c) if (E(a,b).cnt() != 2) mf(f.a, f.b, i, f.c);
C(a, b, c); C(a, c, b); C(b, c, a);
}
}
trav(it, FS) if ((A[it.b] - A[it.a]).cross(
A[it.c] - A[it.a]).dot(it.q) <= 0) swap(it.c, it.b);
return FS;
};