summaryrefslogtreecommitdiff
path: root/geometry
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 /geometry
parentad3856a6b766087df0036de0b556f4700a6498c9 (diff)
parent8d11c6c8213f46f0fa19826917c255edd5d43cb1 (diff)
mzuenni tests
Diffstat (limited to 'geometry')
-rw-r--r--geometry/antipodalPoints.cpp12
-rw-r--r--geometry/circle.cpp33
-rw-r--r--geometry/closestPair.cpp38
-rw-r--r--geometry/convexHull.cpp19
-rw-r--r--geometry/delaunay.cpp124
-rw-r--r--geometry/formulas.cpp42
-rw-r--r--geometry/formulas3d.cpp53
-rw-r--r--geometry/geometry.tex69
-rw-r--r--geometry/hpi.cpp68
-rw-r--r--geometry/lines.cpp33
-rw-r--r--geometry/linesAndSegments.cpp89
-rw-r--r--geometry/polygon.cpp150
-rw-r--r--geometry/segmentIntersection.cpp63
-rw-r--r--geometry/sortAround.cpp10
-rw-r--r--geometry/spheres.cpp29
-rw-r--r--geometry/triangle.cpp43
-rw-r--r--geometry/triangle.tex41
17 files changed, 0 insertions, 916 deletions
diff --git a/geometry/antipodalPoints.cpp b/geometry/antipodalPoints.cpp
deleted file mode 100644
index 110cc74..0000000
--- a/geometry/antipodalPoints.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-vector<pair<int, int>> antipodalPoints(vector<pt>& h) {
- if (sz(h) < 2) return {};
- vector<pair<int, int>> result;
- for (int i = 0, j = 1; i < j; i++) {
- while (true) {
- result.push_back({i, j});
- if (cross(h[(i + 1) % sz(h)] - h[i],
- h[(j + 1) % sz(h)] - h[j]) <= 0) break;
- j = (j + 1) % sz(h);
- }}
- return result;
-}
diff --git a/geometry/circle.cpp b/geometry/circle.cpp
deleted file mode 100644
index fab4150..0000000
--- a/geometry/circle.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// berechnet die Schnittpunkte von zwei Kreisen
-// (Kreise dürfen nicht gleich sein!)
-vector<pt> circleIntersection(pt c1, double r1,
- pt c2, double r2) {
- double d = abs(c1 - c2);
- if (d < abs(r1 - r2) || d > abs(r1 + r2)) return {};
- double a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
- pt p = (c2 - c1) * a / d + c1;
- if (d == abs(r1 - r2) || d == abs(r1 + r2)) return {p};
- double h = sqrt(r1 * r1 - a * a);
- return {p + pt{0, 1} * (c2 - c1) * h / d,
- p - pt{0, 1} * (c2 - c1) * h / d};
-}
-
-// berechnet die Schnittpunkte zwischen
-// einem Kreis(Kugel) und einer Grade (2D und 3D)
-vector<pt> circleRayIntersection(pt center, double r,
- pt orig, pt dir) {
- vector<pt> result;
- double a = dot(dir, dir);
- double b = 2 * dot(dir, orig - center);
- double c = dot(orig - center, orig - center) - r * r;
- double discr = b * b - 4 * a * c;
- if (discr >= 0) {
- //t in [0, 1] => Schnitt mit Segment [orig, orig + dir]
- double t1 = -(b + sqrt(discr)) / (2 * a);
- double t2 = -(b - sqrt(discr)) / (2 * a);
- if (t1 >= 0) result.push_back(t1 * dir + orig);
- if (t2 >= 0 && abs(t1 - t2) > EPS) {
- result.push_back(t2 * dir + orig);
- }}
- return result;
-}
diff --git a/geometry/closestPair.cpp b/geometry/closestPair.cpp
deleted file mode 100644
index a2c91b3..0000000
--- a/geometry/closestPair.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-bool compY(pt a, pt b) {
- return (imag(a) == imag(b)) ? real(a) < real(b)
- : imag(a) < imag(b);
-}
-
-bool compX(pt a, pt b) {
- return (real(a) == real(b)) ? imag(a) < imag(b)
- : real(a) < real(b);
-}
-
-double shortestDist(vector<pt>& pts) { // sz(pts) > 1
- set<pt, bool(*)(pt, pt)> status(compY);
- sort(all(pts), compX);
- double opt = 1.0/0.0, sqrtOpt = 1.0/0.0;
- auto left = pts.begin(), right = pts.begin();
- status.insert(*right); right++;
-
- while (right != pts.end()) {
- if (left != right &&
- abs(real(*left - *right)) >= sqrtOpt) {
- status.erase(*left);
- left++;
- } else {
- auto lower = status.lower_bound({-1.0/0.0, //-INF
- imag(*right) - sqrtOpt});
- auto upper = status.upper_bound({-1.0/0.0, //-INF
- imag(*right) + sqrtOpt});
- for (;lower != upper; lower++) {
- double cand = norm(*right - *lower);
- if (cand < opt) {
- opt = cand;
- sqrtOpt = sqrt(opt);
- }}
- status.insert(*right);
- right++;
- }}
- return sqrtOpt;
-}
diff --git a/geometry/convexHull.cpp b/geometry/convexHull.cpp
deleted file mode 100644
index b1de170..0000000
--- a/geometry/convexHull.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-vector<pt> convexHull(vector<pt> pts){
- sort(all(pts), [](const pt& a, const pt& b){
- return real(a) == real(b) ? imag(a) < imag(b)
- : real(a) < real(b);
- });
- pts.erase(unique(all(pts)), pts.end());
- int k = 0;
- vector<pt> h(2 * sz(pts));
- for (int i = 0; i < sz(pts); i++) {// Untere Hülle.
- while (k > 1 && cross(h[k-2], h[k-1], pts[i]) <= 0) k--;
- h[k++] = pts[i];
- }
- for (int i = sz(pts)-2, t = k; i >= 0; i--) {// Obere Hülle.
- while (k > t && cross(h[k-2], h[k-1], pts[i]) <= 0) k--;
- h[k++] = pts[i];
- }
- h.resize(k);
- return h;
-}
diff --git a/geometry/delaunay.cpp b/geometry/delaunay.cpp
deleted file mode 100644
index 1008b39..0000000
--- a/geometry/delaunay.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-using lll = __int128;
-using pt = complex<ll>;
-
-constexpr pt INF_PT = pt(1e18, 1e18);
-
-bool circ(pt p, pt a, pt b, pt c) {// p in circle(A,B,C)
- return imag((c-b)*conj(p-c)*(a-p)*conj(b-a)) < 0;
-}
-
-struct QuadEdge {
- QuadEdge* rot = nullptr;
- QuadEdge* onext = nullptr;
- pt orig = INF_PT;
- bool used = false;
- QuadEdge* rev() const {return rot->rot;}
- QuadEdge* lnext() const {return rot->rev()->onext->rot;}
- QuadEdge* oprev() const {return rot->onext->rot;}
- pt dest() const {return rev()->orig;}
-};
-
-deque<QuadEdge> edgeData;
-
-QuadEdge* makeEdge(pt from, pt to) {
- for (int j : {0,1,2,3}) edgeData.push_back({});
- auto e = edgeData.end() - 4;
- for (int j : {0,1,2,3}) e[j].onext = e[j^3].rot = &e[j^(j>>1)];
- e[0].orig = from;
- e[1].orig = to;
- return &e[0];
-}
-
-void splice(QuadEdge* a, QuadEdge* b) {
- swap(a->onext->rot->onext, b->onext->rot->onext);
- swap(a->onext, b->onext);
-}
-
-QuadEdge* connect(QuadEdge* a, QuadEdge* b) {
- QuadEdge* e = makeEdge(a->dest(), b->orig);
- splice(e, a->lnext());
- splice(e->rev(), b);
- return e;
-}
-
-bool valid(QuadEdge* e, QuadEdge* base) {
- return cross(e->dest(), base->orig, base->dest()) < 0;
-}
-
-template<bool ccw>
-QuadEdge* deleteAll(QuadEdge* e, QuadEdge* base) {
- if (valid(e, base)) {
- while (circ(base->dest(), base->orig, e->dest(), (ccw ? e->onext : e->oprev())->dest())) {
- QuadEdge* t = ccw ? e->onext : e->oprev();
- splice(e, e->oprev());
- splice(e->rev(), e->rev()->oprev());
- e = t;
- }}
- return e;
-}
-
-template<typename IT>
-pair<QuadEdge*, QuadEdge*> rec(IT l, IT r) {
- int n = distance(l, r);
- if (n <= 3) {
- QuadEdge* a = makeEdge(l[0], l[1]);
- if (n == 2) return {a, a->rev()};
- QuadEdge* b = makeEdge(l[1], l[2]);
- splice(a->rev(), b);
- int side = cross(l[0], l[1], l[2]);
- QuadEdge* c = nullptr;
- if (side != 0) c = connect(b, a);
- if (side >= 0) return {a, b->rev()};
- else return {c->rev(), c};
- }
- auto m = l + (n / 2);
- auto [ldo, ldi] = rec(l, m);
- auto [rdi, rdo] = rec(m, r);
- while (true) {
- if (cross(rdi->orig, ldi->orig, ldi->dest()) > 0) {
- ldi = ldi->lnext();
- } else if (cross(ldi->orig, rdi->orig, rdi->dest()) < 0) {
- rdi = rdi->rev()->onext;
- } else break;
- }
- QuadEdge* base = connect(rdi->rev(), ldi);
- if (ldi->orig == ldo->orig) ldo = base->rev();
- if (rdi->orig == rdo->orig) rdo = base;
- while (true) {
- QuadEdge* lcand = deleteAll<true>(base->rev()->onext, base);
- QuadEdge* rcand = deleteAll<false>(base->oprev(), base);
- if (!valid(lcand, base) && !valid(rcand, base)) break;
- if (!valid(lcand, base) || (valid(rcand, base) &&
- circ(lcand->dest(), lcand->orig, rcand->orig, rcand->dest()))) {
- base = connect(rcand, base->rev());
- } else {
- base = connect(base->rev(), lcand->rev());
- }}
- return {ldo, rdo};
-}
-
-vector<pt> delaunay(vector<pt> pts) {
- if (sz(pts) <= 2) return {};
- sort(all(pts), [](const pt& a, const pt& b) {
- if (real(a) != real(b)) return real(a) < real(b);
- return imag(a) < imag(b);
- });
- QuadEdge* r = rec(all(pts)).first;
- vector<QuadEdge*> edges = {r};
- while (cross(r->onext->dest(), r->dest(), r->orig) < 0) r = r->onext;
- auto add = [&](QuadEdge* e){
- QuadEdge* cur = e;
- do {
- cur->used = true;
- pts.push_back(cur->orig);
- edges.push_back(cur->rev());
- cur = cur->lnext();
- } while (cur != e);
- };
- add(r);
- pts.clear();
- for (int i = 0; i < sz(edges); i++) {
- if (!edges[i]->used) add(edges[i]);
- }
- return pts;
-}
diff --git a/geometry/formulas.cpp b/geometry/formulas.cpp
deleted file mode 100644
index 22e9e32..0000000
--- a/geometry/formulas.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-// Komplexe Zahlen als Punkte. Wenn immer möglich complex<ll>
-// verwenden. Funktionen wie abs() geben dann aber ll zurück.
-using pt = complex<double>;
-
-constexpr double PIU = acos(-1.0l); // PIL < PI < PIU
-constexpr double PIL = PIU-2e-19l;
-
-// Winkel zwischen Punkt und x-Achse in [-PI, PI].
-double angle(pt a) {return arg(a);}
-
-// rotiert Punkt im Uhrzeigersinn um den Ursprung.
-pt rotate(pt a, double theta) {return a * polar(1.0, theta);}
-
-// Skalarprodukt.
-double dot(pt a, pt b) {return real(conj(a) * b);}
-
-// abs()^2.(pre c++20)
-double norm(pt a) {return dot(a, a);}
-
-// Kreuzprodukt, 0, falls kollinear.
-double cross(pt a, pt b) {return imag(conj(a) * b);}
-double cross(pt p, pt a, pt b) {return cross(a - p, b - p);}
-
-// 1 => c links von a->b
-// 0 => a, b und c kolliniear
-// -1 => c rechts von a->b
-int orientation(pt a, pt b, pt c) {
- double orien = cross(b - a, c - a);
- return (orien > EPS) - (orien < -EPS);
-}
-
-// Liegt d in der gleichen Ebene wie a, b, und c?
-bool isCoplanar(pt a, pt b, pt c, pt d) {
- return abs((b - a) * (c - a) * (d - a)) < EPS;
-}
-
-// charakterisiert winkel zwischen Vektoren u und v
-pt uniqueAngle(pt u, pt v) {
- pt tmp = v * conj(u);
- ll g = abs(gcd(real(tmp), imag(tmp)));
- return tmp / g;
-}
diff --git a/geometry/formulas3d.cpp b/geometry/formulas3d.cpp
deleted file mode 100644
index 84e17c0..0000000
--- a/geometry/formulas3d.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Skalarprodukt
-double operator|(pt3 a, pt3 b) {
- return a.x * b.x + a.y*b.y + a.z*b.z;
-}
-double dot(pt3 a, pt3 b) {return a|b;}
-
-// Kreuzprodukt
-pt3 operator*(pt3 a, pt3 b) {return {a.y*b.z - a.z*b.y,
- a.z*b.x - a.x*b.z,
- a.x*b.y - a.y*b.x};}
-pt3 cross(pt3 a, pt3 b) {return a*b;}
-
-// Länge von a
-double abs(pt3 a) {return sqrt(dot(a, a));}
-double abs(pt3 a, pt3 b) {return abs(b - a);}
-
-// Mixedprodukt
-double mixed(pt3 a, pt3 b, pt3 c) {return a*b|c;};
-
-// orientierung von p zu der Ebene durch a, b, c
-// -1 => gegen den Uhrzeigersinn,
-// 0 => kolliniear,
-// 1 => im Uhrzeigersinn.
-int orientation(pt3 a, pt3 b, pt3 c, pt3 p) {
- double orien = mixed(b - a, c - a, p - a);
- return (orien > EPS) - (orien < -EPS);
-}
-
-// Entfernung von Punkt p zur Ebene a,b,c.
-double distToPlane(pt3 a, pt3 b, pt3 c, pt3 p) {
- pt3 n = cross(b-a, c-a);
- return (abs(dot(n, p)) - dot(n, a)) / abs(n);
-}
-
-// Liegt p in der Ebene a,b,c?
-bool pointOnPlane(pt3 a, pt3 b, pt3 c, pt3 p) {
- return orientation(a, b, c, p) == 0;
-}
-
-// Schnittpunkt von der Grade a-b und der Ebene c,d,e
-// die Grade darf nicht parallel zu der Ebene sein!
-pt3 linePlaneIntersection(pt3 a, pt3 b, pt3 c, pt3 d, pt3 e) {
- pt3 n = cross(d-c, e-c);
- pt3 d = b - a;
- return a - d * (dot(n, a) - dot(n, c)) / dot(n, d);
-}
-
-// Abstand zwischen der Grade a-b und c-d
-double lineLineDist(pt3 a, pt3 b, pt3 c, pt3 d) {
- pt3 n = cross(b - a, d - c);
- if (abs(n) < EPS) return distToLine(a, b, c);
- return abs(dot(a - c, n)) / abs(n);
-}
diff --git a/geometry/geometry.tex b/geometry/geometry.tex
deleted file mode 100644
index 57c8092..0000000
--- a/geometry/geometry.tex
+++ /dev/null
@@ -1,69 +0,0 @@
-\section{Geometrie}
-
-\begin{algorithm}{Closest Pair}
- \begin{methods}
- \method{shortestDist}{kürzester Abstand zwischen Punkten}{n\*\log(n)}
- \end{methods}
- \sourcecode{geometry/closestPair.cpp}
-\end{algorithm}
-
-\begin{algorithm}{Rotating calipers}
- \begin{methods}
- \method{antipodalPoints}{berechnet antipodale Punkte}{n}
- \end{methods}
- \textbf{WICHTIG:} Punkte müssen gegen den Uhrzeigersinn sortiert sein und konvexes Polygon bilden!
- \sourcecode{geometry/antipodalPoints.cpp}
-\end{algorithm}
-
-\begin{algorithm}{Konvexe Hülle}
- \begin{methods}
- \method{convexHull}{berechnet konvexe Hülle}{n\*\log(n)}
- \end{methods}
- \begin{itemize}
- \item konvexe Hülle gegen den Uhrzeigersinn sortiert
- \item nur Eckpunkte enthalten(für alle Punkte = im CCW Test entfernen)
- \item erster und letzter Punkt sind identisch
- \end{itemize}
- \sourcecode{geometry/convexHull.cpp}
-\end{algorithm}
-
-\subsection{Formeln~~--~\texttt{std::complex}}
-\sourcecode{geometry/formulas.cpp}
-\sourcecode{geometry/linesAndSegments.cpp}
-\sourcecode{geometry/sortAround.cpp}
-\input{geometry/triangle}
-\sourcecode{geometry/triangle.cpp}
-\sourcecode{geometry/polygon.cpp}
-\sourcecode{geometry/circle.cpp}
-
-\subsection{Formeln -- 3D}
-\sourcecode{geometry/formulas3d.cpp}
-
-\optional{
- \subsection{3D-Kugeln \opthint}
- \sourcecode{geometry/spheres.cpp}
-}
-
-\begin{algorithm}{Half-plane intersection}
- \sourcecode{geometry/hpi.cpp}
-\end{algorithm}
-
-\begin{algorithm}[optional]{Intersecting Segments}
- \begin{methods}
- \method{intersect}{finds ids of intersecting segments}{n\*\log(n)}
- \end{methods}
- \sourcecode{geometry/segmentIntersection.cpp}
-\end{algorithm}
-
-\begin{algorithm}[optional]{Delaunay Triangulierung}
- \begin{methods}
- \method{delaunay}{berechnet Triangulierung}{n\*\log(n)}
- \end{methods}
- \textbf{WICHTIG:} Wenn alle Punkte kollinear sind gibt es keine Triangulierung! Wenn 4 Punkte auf einem Kreis liegen ist die Triangulierung nicht eindeutig.
- \sourcecode{geometry/delaunay.cpp}
-\end{algorithm}
-
-\optional{
-\subsection{Geraden \opthint}
-\sourcecode{geometry/lines.cpp}
-}
diff --git a/geometry/hpi.cpp b/geometry/hpi.cpp
deleted file mode 100644
index 3509e0e..0000000
--- a/geometry/hpi.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-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;
-}
diff --git a/geometry/lines.cpp b/geometry/lines.cpp
deleted file mode 100644
index 95536a4..0000000
--- a/geometry/lines.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-struct line {
- double a, b, c; // ax + by + c = 0; vertikale Line: b = 0, sonst: b = 1
- line(pt p, pt q) : a(-imag(q-p)), b(real(q-p)), c(cross({b, -a},p)) {}
-};
-
-line pointsToLine(pt p1, pt p2) {
- line l;
- if (abs(real(p1 - p2)) < EPS) {
- l.a = 1; l.b = 0.0; l.c = -real(p1);
- } else {
- l.a = -imag(p1 - p2) / real(p1 - p2);
- l.b = 1.0;
- l.c = -(l.a * real(p1)) - imag(p1);
- }
- return l;
-}
-
-bool parallel(line l1, line l2) {
- return (abs(l1.a - l2.a) < EPS) && (abs(l1.b - l2.b) < EPS);
-}
-
-bool same(line l1, line l2) {
- return parallel(l1, l2) && (abs(l1.c - l2.c) < EPS);
-}
-
-bool intersect(line l1, line l2, pt& p) {
- if (parallel(l1, l2)) return false;
- double y, x = (l2.b * l1.c - l1.b * l2.c) / (l2.a * l1.b - l1.a * l2.b);
- if (abs(l1.b) > EPS) y = -(l1.a * x + l1.c);
- else y = -(l2.a * x + l2.c);
- p = {x, y};
- return true;
-}
diff --git a/geometry/linesAndSegments.cpp b/geometry/linesAndSegments.cpp
deleted file mode 100644
index 98fe4dc..0000000
--- a/geometry/linesAndSegments.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-// Test auf Streckenschnitt zwischen a-b und c-d.
-bool lineSegmentIntersection(pt a, pt b, pt c, pt d) {
- if (orientation(a, b, c) == 0 && orientation(a, b, d) == 0)
- return pointOnLineSegment(a,b,c) ||
- pointOnLineSegment(a,b,d) ||
- pointOnLineSegment(c,d,a) ||
- pointOnLineSegment(c,d,b);
- return orientation(a, b, c) * orientation(a, b, d) <= 0 &&
- orientation(c, d, a) * orientation(c, d, b) <= 0;
-}
-
-// Berechnet die Schnittpunkte der Strecken p0-p1 und p2-p3.
-// Enthält entweder keinen Punkt, den einzigen Schnittpunkt
-// oder die Endpunkte der Schnittstrecke.
-vector<pt> lineSegmentIntersection(pt p0, pt p1, pt p2, pt p3) {
- double a = cross(p1 - p0, p3 - p2);
- double b = cross(p2 - p0, p3 - p2);
- double c = cross(p1 - p0, p0 - p2);
- if (a < 0) {a = -a; b = -b; c = -c;}
- if (b < -EPS || b-a > EPS || c < -EPS || c-a > EPS) return {};
- if (a > EPS) return {p0 + b/a*(p1 - p0)};
- vector<pt> result;
- auto insertUnique = [&](pt p) {
- for (auto q: result) if (abs(p - q) < EPS) return;
- result.push_back(p);
- };
- if (dot(p2-p0, p3-p0) < EPS) insertUnique(p0);
- if (dot(p2-p1, p3-p1) < EPS) insertUnique(p1);
- if (dot(p0-p2, p1-p2) < EPS) insertUnique(p2);
- if (dot(p0-p3, p1-p3) < EPS) insertUnique(p3);
- return result;
-}
-
-// Entfernung von Punkt p zur Geraden durch a-b. 2d und 3d
-double distToLine(pt a, pt b, pt p) {
- return abs(cross(p - a, b - a)) / abs(b - a);
-}
-
-// Projiziert p auf die Gerade a-b
-pt projectToLine(pt a, pt b, pt p) {
- return a + (b - a) * dot(p - a, b - a) / norm(b - a);
-}
-
-// Liegt p auf der Geraden a-b? 2d und 3d
-bool pointOnLine(pt a, pt b, pt p) {
- return cross(a, b, p) == 0;
-}
-
-// Test auf Linienschnitt zwischen a-b und c-d.
-bool lineIntersection(pt a, pt b, pt c, pt d) {
- return abs(cross(a - b, c - d)) < EPS;
-}
-
-// Berechnet den Schnittpunkt der Graden p0-p1 und p2-p3.
-// die Graden dürfen nicht parallel sein!
-pt lineIntersection(pt p0, pt p1, pt p2, pt p3) {
- double a = cross(p1 - p0, p3 - p2);
- double b = cross(p2 - p0, p3 - p2);
- return {p0 + b/a*(p1 - p0)};
-}
-
-// Liegt p auf der Strecke a-b?
-bool pointOnLineSegment(pt a, pt b, pt p) {
- if (cross(a, b, p) != 0) return false;
- double dist = norm(a - b);
- return norm(a - p) <= dist && norm(b - p) <= dist;
-}
-
-// Entfernung von Punkt p zur Strecke a-b.
-double distToSegment(pt a, pt b, pt p) {
- if (a == b) return abs(p - a);
- if (dot(p - a, b - a) <= 0) return abs(p - a);
- if (dot(p - b, b - a) >= 0) return abs(p - b);
- return distToLine(a, b, p);
-}
-
-// Kürzeste Entfernung zwischen den Strecken a-b und c-d.
-double distBetweenSegments(pt a, pt b, pt c, pt d) {
- if (lineSegmentIntersection(a, b, c, d)) return 0.0;
- return min({distToSegment(a, b, c), distToSegment(a, b, d),
- distToSegment(c, d, a), distToSegment(c, d, b)});
-}
-
-// sortiert alle Punkte pts auf einer Linie entsprechend dir
-void sortLine(pt dir, vector<pt>& pts) { // (2d und 3d)
- sort(all(pts), [&](pt a, pt b){
- return dot(dir, a) < dot(dir, b);
- });
-}
diff --git a/geometry/polygon.cpp b/geometry/polygon.cpp
deleted file mode 100644
index e3ce33e..0000000
--- a/geometry/polygon.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-// Flächeninhalt eines Polygons (nicht selbstschneidend).
-// Punkte gegen den Uhrzeigersinn: positiv, sonst negativ.
-double area(const vector<pt>& poly) { //poly[0] == poly.back()
- double res = 0;
- for (int i = 0; i + 1 < sz(poly); i++)
- res += cross(poly[i], poly[i + 1]);
- return 0.5 * res;
-}
-
-// Anzahl drehungen einer Polyline um einen Punkt
-// p nicht auf rand und poly[0] == poly.back()
-// res != 0 or (res & 1) != 0 um inside zu prüfen bei
-// selbstschneidenden Polygonen (definitions Sache)
-ll windingNumber(pt p, const vector<pt>& poly) {
- ll res = 0;
- for (int i = 0; i + 1 < sz(poly); i++) {
- pt a = poly[i], b = poly[i + 1];
- if (real(a) > real(b)) swap(a, b);
- if (real(a) <= real(p) && real(p) < real(b) &&
- cross(p, a, b) < 0) {
- res += orientation(p, poly[i], poly[i + 1]);
- }}
- return res;
-}
-
-// Testet, ob ein Punkt im Polygon liegt (beliebige Polygone).
-// Ändere Zeile 32 falls rand zählt, poly[0] == poly.back()
-bool inside(pt p, const vector<pt>& poly) {
- bool in = false;
- for (int i = 0; i + 1 < sz(poly); i++) {
- pt a = poly[i], b = poly[i + 1];
- if (pointOnLineSegment(a, b, p)) return false;
- if (real(a) > real(b)) swap(a,b);
- if (real(a) <= real(p) && real(p) < real(b) &&
- cross(p, a, b) < 0) {
- in ^= 1;
- }}
- return in;
-}
-
-// convex hull without duplicates, h[0] != h.back()
-// apply comments if border counts as inside
-bool inside(pt p, const vector<pt>& hull) {
- int l = 0, r = sz(hull) - 1;
- if (cross(hull[0], hull[r], p) >= 0) return false; // > 0
- while (l + 1 < r) {
- int m = (l + r) / 2;
- if (cross(hull[0], hull[m], p) > 0) l = m; // >= 0
- else r = m;
- }
- return cross(hull[l], hull[r], p) > 0; // >= 0
-}
-
-void rotateMin(vector<pt>& hull) {
- auto mi = min_element(all(hull), [](const pt& a, const pt& b){
- return real(a) == real(b) ? imag(a) < imag(b)
- : real(a) < real(b);
- });
- rotate(hull.begin(), mi, hull.end());
-}
-
-// convex hulls without duplicates, h[0] != h.back()
-vector<pt> minkowski(vector<pt> ps, vector<pt> qs) {
- rotateMin(ps);
- rotateMin(qs);
- ps.push_back(ps[0]);
- qs.push_back(qs[0]);
- ps.push_back(ps[1]);
- qs.push_back(qs[1]);
- vector<pt> res;
- for (ll i = 0, j = 0; i + 2 < sz(ps) || j + 2 < sz(qs);) {
- res.push_back(ps[i] + qs[j]);
- auto c = cross(ps[i + 1] - ps[i], qs[j + 1] - qs[j]);
- if(c >= 0) i++;
- if(c <= 0) j++;
- }
- return res;
-}
-
-// convex hulls without duplicates, h[0] != h.back()
-double dist(const vector<pt>& ps, const vector<pt>& qs) {
- for (pt& q : qs) q *= -1;
- auto p = minkowski(ps, qs);
- p.push_back(p[0]);
- double res = 0.0;
- //bool intersect = true;
- for (ll i = 0; i + 1 < sz(p); i++) {
- //intersect &= cross(p[i], p[i+1] - p[i]) <= 0;
- res = max(res, cross(p[i], p[i+1]-p[i]) / abs(p[i+1]-p[i]));
- }
- return res;
-}
-
-bool left(pt of, pt p) {return cross(p, of) < 0 ||
- (cross(p, of) == 0 && dot(p, of) > 0);}
-
-// convex hulls without duplicates, hull[0] == hull.back() and
-// hull[0] must be a convex point (with angle < pi)
-// returns index of corner where dot(dir, corner) is maximized
-int extremal(const vector<pt>& hull, pt dir) {
- dir *= pt(0, 1);
- int l = 0, r = sz(hull) - 1;
- while (l + 1 < r) {
- int m = (l + r) / 2;
- pt dm = hull[m+1]-hull[m];
- pt dl = hull[l+1]-hull[l];
- if (left(dl, dir) != left(dl, dm)) {
- if (left(dl, dm)) l = m;
- else r = m;
- } else {
- if (cross(dir, dm) < 0) l = m;
- else r = m;
- }}
- return r;
-}
-
-// convex hulls without duplicates, hull[0] == hull.back() and
-// hull[0] must be a convex point (with angle < pi)
-// {} if no intersection
-// {x} if corner is only intersection
-// {a, b} segments (a,a+1) and (b,b+1) intersected (if only the
-// border is intersected corners a and b are the start and end)
-vector<int> intersect(const vector<pt>& hull, pt a, pt b) {
- int endA = extremal(hull, (a-b) * pt(0, 1));
- int endB = extremal(hull, (b-a) * pt(0, 1));
- // cross == 0 => line only intersects border
- if (cross(hull[endA], a, b) > 0 ||
- cross(hull[endB], a, b) < 0) return {};
-
- int n = sz(hull) - 1;
- vector<int> res;
- for (auto _ : {0, 1}) {
- int l = endA, r = endB;
- if (r < l) r += n;
- while (l + 1 < r) {
- int m = (l + r) / 2;
- if (cross(hull[m % n], a, b) <= 0 &&
- cross(hull[m % n], a, b) != hull(poly[endB], a, b))
- l = m;
- else r = m;
- }
- if (cross(hull[r % n], a, b) == 0) l++;
- res.push_back(l % n);
- swap(endA, endB);
- swap(a, b);
- }
- if (res[0] == res[1]) res.pop_back();
- return res;
-}
-
diff --git a/geometry/segmentIntersection.cpp b/geometry/segmentIntersection.cpp
deleted file mode 100644
index 6dc5dc5..0000000
--- a/geometry/segmentIntersection.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-struct seg {
- pt a, b;
- int id;
- bool operator<(const seg& o) const {
- if (real(a) < real(o.a)) {
- int s = orientation(a, b, o.a);
- return (s > 0 || (s == 0 && imag(a) < imag(o.a)));
- } else if (real(a) > real(o.a)) {
- int s = orientation(o.a, o.b, a);
- return (s < 0 || (s == 0 && imag(a) < imag(o.a)));
- }
- return imag(a) < imag(o.a);
- }
-};
-
-struct event {
- pt p;
- int id, type;
- bool operator<(const event& o) const {
- if (real(p) != real(o.p)) return real(p) < real(o.p);
- if (type != o.type) return type > o.type;
- return imag(p) < imag(o.p);
- }
-};
-
-bool lessPT(const pt& a, const pt& b) {
- return real(a) != real(b) ? real(a) < real(b)
- : imag(a) < imag(b);
-}
-
-bool intersect(const seg& a, const seg& b) {
- return lineSegmentIntersection(a.a, a.b, b.a, b.b);
-}
-
-pair<int, int> intersect(vector<seg>& segs) {
- vector<event> events;
- for (seg& s : segs) {
- if (lessPT(s.b, s.a)) swap(s.b, s.a);
- events.push_back({s.a, s.id, 1});
- events.push_back({s.b, s.id, -1});
- }
- sort(all(events));
-
- set<seg> q;
- vector<set<seg>::iterator> where(sz(segs));
- for (auto e : events) {
- int id = e.id;
- if (e.type > 0) {
- auto it = q.lower_bound(segs[id]);
- if (it != q.end() && intersect(*it, segs[id]))
- return {it->id, segs[id].id};
- if (it != q.begin() && intersect(*prev(it), segs[id]))
- return {prev(it)->id, segs[id].id};
- where[id] = q.insert(it, segs[id]);
- } else {
- auto it = where[id];
- if (it != q.begin() && next(it) != q.end() && intersect(*next(it), *prev(it)))
- return {next(it)->id, prev(it)->id};
- q.erase(it);
- }
- }
- return {-1, -1};
-}
diff --git a/geometry/sortAround.cpp b/geometry/sortAround.cpp
deleted file mode 100644
index 86fead7..0000000
--- a/geometry/sortAround.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-bool left(pt p) {return real(p) < 0 ||
- (real(p) == 0 && imag(p) < 0);}
-
-void sortAround(pt p, vector<pt>& ps) {
- sort(all(ps), [&](const pt& a, const pt& b){
- if (left(a - p) != left(b - p))
- return left(a - p) > left(b - p);
- return cross(p, a, b) > 0;
- });
-}
diff --git a/geometry/spheres.cpp b/geometry/spheres.cpp
deleted file mode 100644
index b5d3644..0000000
--- a/geometry/spheres.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// Great Circle Distance mit Längen- und Breitengrad.
-double gcDist(double pLat, double pLon,
- double qLat, double qLon, double radius) {
- pLat *= PI / 180; pLon *= PI / 180;
- qLat *= PI / 180; qLon *= PI / 180;
- return radius * acos(cos(pLat) * cos(pLon) *
- cos(qLat) * cos(qLon) +
- cos(pLat) * sin(pLon) *
- cos(qLat) * sin(qLon) +
- sin(pLat) * sin(qLat));
-}
-
-// Great Circle Distance mit kartesischen Koordinaten.
-double gcDist(point p, point q) {
- return acos(p.x * q.x + p.y * q.y + p.z * q.z);
-}
-
-// 3D Punkt in kartesischen Koordinaten.
-struct point{
- double x, y, z;
- point() {}
- point(double x, double y, double z) : x(x), y(y), z(z) {}
- point(double lat, double lon) {
- lat *= PI / 180.0; lon *= PI / 180.0;
- x = cos(lat) * sin(lon);
- y = cos(lat) * cos(lon);
- z = sin(lat);
- }
-};
diff --git a/geometry/triangle.cpp b/geometry/triangle.cpp
deleted file mode 100644
index 33a8394..0000000
--- a/geometry/triangle.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Mittelpunkt des Dreiecks abc.
-pt centroid(pt a, pt b, pt c) {return (a + b + c) / 3.0;}
-
-// Flächeninhalt eines Dreicks bei bekannten Eckpunkten.
-double area(pt a, pt b, pt c) {
- return abs(cross(b - a, c - a)) / 2.0;
-}
-
-// Flächeninhalt eines Dreiecks bei bekannten Seitenlängen.
-double area(double a, double b, double c) {
- double s = (a + b + c) / 2.0;
- return sqrt(s * (s-a) * (s-b) * (s-c));
-}
-
-// Zentrum des größten Kreises im Dreiecke
-pt inCenter(pt a, pt b, pt c) {
- double x = abs(a-b), y = abs(b-c), z = abs(a-c);
- return (y*a + z*b + x*c) / (x+y+z);
-}
-
-// Zentrum des Kreises durch alle Eckpunkte
-// a, b und c nicht kollinear
-pt circumCenter(pt a, pt b, pt c) {
- b -= a, c -= a;
- pt d = b * norm(c) - c * norm(b);
- d = {-d.imag(), d.real()};
- return a + d / cross(b, c) / 2.0;
-}
-
-// 1 => p außerhalb Kreis durch a,b,c
-// 0 => p auf Kreis durch a,b,c
-// -1 => p im Kreis durch a,b,c
-int insideOutCenter(pt a, pt b, pt c, pt p) {// braucht lll
- return sgn(imag((c-b)*conj(p-c)*(a-p)*conj(b-a)));
-}
-
-// Sind die Dreiecke a1, b1, c1, and a2, b2, c2 ähnlich?
-// Erste Zeile testet Ähnlichkeit mit gleicher Orientierung,
-// zweite Zeile testet Ähnlichkeit mit verschiedener Orientierung
-bool similar(pt a1, pt b1, pt c1, pt a2, pt b2, pt c2) {
- return (b2-a2) * (c1-a1) == (b1-a1) * (c2-a2) ||
- (b2-a2) * conj(c1-a1) == conj(b1-a1) * (c2-a2);
-}
diff --git a/geometry/triangle.tex b/geometry/triangle.tex
deleted file mode 100644
index 3decd54..0000000
--- a/geometry/triangle.tex
+++ /dev/null
@@ -1,41 +0,0 @@
-
-\begin{minipage}[T]{0.27\linewidth}
- Generell:
- \begin{itemize}
- \item $\cos(\gamma)=\frac{a^2+b^2-c^2}{2ab}$
- \item $b=\frac{a}{\sin(\alpha)}\sin(\beta)$
- %\item $b=\frac{a}{\sin(\pi-\beta-\gamma)}\sin(\beta)$
- %\item $\sin(\beta)=\frac{b\sin(\alpha)}{a}$ %asin is not uniquely invertible
- \item $\Delta=\frac{bc}{2}\sin(\alpha)$
- \end{itemize}
-\end{minipage}
-\hfill
-\begin{minipage}[B]{0.5\linewidth}
- \centering
- \begin{tikzpicture}[line cap=round,minimum size=0,x=.7cm,y=0.7cm]
- \node[circle,inner sep=0] (AA) at (0,0) {$A$};
- \node[circle,inner sep=0] (BB) at (3,-1) {$B$};
- \node[circle,inner sep=0] (CC) at (3.666667,1) {$C$};
-
- \coordinate (A) at (AA.0);
- \coordinate (B) at (BB.100);
- \coordinate (C) at (CC.210);
-
- \pic[draw,angle radius=15,pic text=$\gamma$]{angle = A--C--B};
- \pic[draw,angle radius=15,pic text=$\beta$]{angle = C--B--A};
- \pic[draw,angle radius=20,pic text=$\alpha$]{angle = B--A--C};
-
- \draw (A) to[edge label={$b$},inner sep=1] (C);
- \draw (A) to[edge label'={$c$},inner sep=1.3] (B);
- \draw (B) to[edge label'={$a$},inner sep=0.6] (C);
- \end{tikzpicture}
-\end{minipage}
-\hfill
-\begin{minipage}[T]{0.16\linewidth}
- $\beta=90^\circ$:
- \begin{itemize}
- \item $\sin(\alpha)=\frac{a}{b}$
- \item $\cos(\alpha)=\frac{c}{b}$
- \item $\tan(\alpha)=\frac{a}{c}$
- \end{itemize}
-\end{minipage}