teamnote default
This commit is contained in:
50
source/Geometry/HPI.cpp
Normal file
50
source/Geometry/HPI.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
using ld = long double;
|
||||
using pdd = pair<ld, ld>;
|
||||
using line = pair<pdd, pdd>; // half plane : left side of vector fi->se
|
||||
|
||||
const ld eps = 1e-9;
|
||||
pdd operator*(const pdd& a, ld s) { return {a.fi * s, a.se * s}; }
|
||||
inline bool equals(ld a, ld b) { return abs(a - b) < eps; }
|
||||
|
||||
bool line_intersect(line& a, line& b, pdd& v) {
|
||||
ld det = (a.se - a.fi) / (b.se - b.fi);
|
||||
if (equals(det, 0)) return 0;
|
||||
ld t = ((b.fi - a.fi) / (b.se - b.fi)) / det;
|
||||
v = a.fi + (a.se - a.fi) * t;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool bad(line& a, line& b, line& c) {
|
||||
pdd v; if(!line_intersect(a, b, v)) return 0;
|
||||
return (c.se - c.fi) / (v - c.fi) <= eps;
|
||||
}
|
||||
|
||||
vector<pdd> HPI(vector<line>& lns) {
|
||||
auto lsgn = [&](const line& a) {
|
||||
if(a.fi.se == a.se.se) return a.fi.fi > a.se.fi;
|
||||
return a.fi.se > a.se.se;
|
||||
};
|
||||
sort(lns.begin(), lns.end(), [&](const line& a, const line& b) {
|
||||
if(lsgn(a) != lsgn(b)) return lsgn(a) < lsgn(b);
|
||||
return (a.se - a.fi) / (b.se - b.fi) > 0;
|
||||
});
|
||||
|
||||
deque<line> dq;
|
||||
for(auto l : lns){
|
||||
while(dq.size() >= 2 && bad(dq[dq.size()-2], dq.back(), l)) dq.pop_back();
|
||||
while(dq.size() >= 2 && bad(dq[0], dq[1], l)) dq.pop_front();
|
||||
|
||||
if(dq.size() < 2 || !bad(dq.back(), l, dq[0])) dq.pb(l);
|
||||
}
|
||||
|
||||
vector<pdd> res;
|
||||
if(dq.size() >= 3) {
|
||||
for(int i = 0; i < (int)dq.size(); i++) {
|
||||
int j = (i + 1) % (int)dq.size();
|
||||
pdd v;
|
||||
if(!line_intersect(dq[i], dq[j], v)) continue;
|
||||
res.push_back(v);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
Reference in New Issue
Block a user