diff options
Diffstat (limited to 'geometry')
| -rw-r--r-- | geometry/antipodalPoints.cpp | 12 | ||||
| -rw-r--r-- | geometry/circle.cpp | 33 | ||||
| -rw-r--r-- | geometry/closestPair.cpp | 38 | ||||
| -rw-r--r-- | geometry/convexHull.cpp | 19 | ||||
| -rw-r--r-- | geometry/delaunay.cpp | 124 | ||||
| -rw-r--r-- | geometry/formulas.cpp | 42 | ||||
| -rw-r--r-- | geometry/formulas3d.cpp | 53 | ||||
| -rw-r--r-- | geometry/geometry.tex | 69 | ||||
| -rw-r--r-- | geometry/hpi.cpp | 68 | ||||
| -rw-r--r-- | geometry/lines.cpp | 33 | ||||
| -rw-r--r-- | geometry/linesAndSegments.cpp | 89 | ||||
| -rw-r--r-- | geometry/polygon.cpp | 150 | ||||
| -rw-r--r-- | geometry/segmentIntersection.cpp | 63 | ||||
| -rw-r--r-- | geometry/sortAround.cpp | 10 | ||||
| -rw-r--r-- | geometry/spheres.cpp | 29 | ||||
| -rw-r--r-- | geometry/triangle.cpp | 43 | ||||
| -rw-r--r-- | geometry/triangle.tex | 41 |
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} |
