summaryrefslogtreecommitdiff
path: root/content/geometry/hpi.cpp
diff options
context:
space:
mode:
authorGloria Mundi <gloria@gloria-mundi.eu>2024-11-16 01:24:14 +0100
committerGloria Mundi <gloria@gloria-mundi.eu>2024-11-16 01:24:14 +0100
commit98567ec798aa8ca2cfbcb85c774dd470f30e30d4 (patch)
tree5113d5cc24d1ad5f93810b6442ce584a36950dc8 /content/geometry/hpi.cpp
parentad3856a6b766087df0036de0b556f4700a6498c9 (diff)
parent8d11c6c8213f46f0fa19826917c255edd5d43cb1 (diff)
mzuenni tests
Diffstat (limited to 'content/geometry/hpi.cpp')
-rw-r--r--content/geometry/hpi.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/content/geometry/hpi.cpp b/content/geometry/hpi.cpp
new file mode 100644
index 0000000..3509e0e
--- /dev/null
+++ b/content/geometry/hpi.cpp
@@ -0,0 +1,68 @@
+constexpr ll inf = 0x1FFF'FFFF'FFFF'FFFF;//THIS CODE IS WIP
+
+bool left(pt p) {return real(p) < 0 ||
+ (real(p) == 0 && imag(p) < 0);}
+struct hp {
+ pt from, to;
+
+ hp(pt a, pt b) : from(a), to(b) {}
+ hp(pt dummy) : hp(dummy, dummy) {}
+
+ bool dummy() const {return from == to;}
+ pt dir() const {return dummy() ? to : to - from;}
+ bool operator<(const hp& o) const {
+ if (left(dir()) != left(o.dir()))
+ return left(dir()) > left(o.dir());
+ return cross(dir(), o.dir()) > 0;
+ }
+
+ using lll = __int128;
+ using ptl = complex<lll>;
+ ptl mul(lll m, ptl p) const {return m*p;}//ensure 128bit
+
+ bool check(const hp& a, const hp& b) const {
+ if (dummy() || b.dummy()) return false;
+ if (a.dummy()) {
+ ll ort = sgn(cross(b.dir(), dir()));
+ if (ort == 0) return cross(from, to, a.from) < 0;
+ return cross(b.dir(), a.dir()) * ort > 0;
+ }
+ ll y = cross(a.dir(), b.dir());
+ ll z = cross(b.from - a.from, b.dir());
+ ptl i = mul(y, a.from) + mul(z, a.dir()); //intersect a and b
+ // check if i is outside/right of x
+ return imag(conj(mul(sgn(y),dir()))*(i-mul(y,from))) < 0;
+ }
+};
+
+constexpr ll lim = 2e9+7;
+
+deque<hp> intersect(vector<hp> hps) {
+ hps.push_back(hp(pt{lim+1,-1}));
+ hps.push_back(hp(pt{lim+1,1}));
+ sort(all(hps));
+
+ deque<hp> dq = {hp(pt{-lim, 1})};
+ for (auto x : hps) {
+ while (sz(dq) > 1 && x.check(dq.end()[-1], dq.end()[-2]))
+ dq.pop_back();
+ while (sz(dq) > 1 && x.check(dq[0], dq[1]))
+ dq.pop_front();
+
+ if (cross(x.dir(), dq.back().dir()) == 0) {
+ if (dot(x.dir(), dq.back().dir()) < 0) return {};
+ if (cross(x.from, x.to, dq.back().from) < 0)
+ dq.pop_back();
+ else continue;
+ }
+ dq.push_back(x);
+ }
+
+ while (sz(dq) > 2 && dq[0].check(dq.end()[-1], dq.end()[-2]))
+ dq.pop_back();
+ while (sz(dq) > 2 && dq.end()[-1].check(dq[0], dq[1]))
+ dq.pop_front();
+
+ if (sz(dq) < 3) return {};
+ return dq;
+}