Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- #define all(x) (x).begin(),(x).end()
- using namespace std;
- using ld = long double;
- const ld PI = acosl(-1.0);
- ld CrossC(ld r1, ld r2, ld dx, ld dy) {
- ld dist = sqrtl(dx * dx + dy * dy);
- if (r1 > r2) swap(r1, r2);
- if (r2 >= dist + r1) return r1 * r1 * PI;
- if (r1 + r2 <= dist) return 0;
- ld a = 2 * acosl((r1 * r1 + dist * dist - r2 * r2) / 2 / r1 / dist);
- ld b = 2 * acosl((r2 * r2 + dist * dist - r1 * r1) / 2 / r2 / dist);
- ld ans = r1 * r1 / 2 * (a - sinl(a)) + r2 * r2 / 2 * (b - sinl(b));
- return ans;
- }
- ld S(ld r, ld h, ld g) {
- assert(h >= 0 && g >= 0);
- assert(h <= r && g <= r);
- ld a = sqrtl(r * r - h * h) - g;
- ld b = sqrtl(r * r - g * g) - h;
- if (a < 0 || b < 0) return 0;
- ld c = sqrtl(a * a + b * b);
- ld ans = a * b / 2;
- ld A = 2 * asinl(c / 2 / r);
- ans += r * r / 2 * (A - sinl(A));
- return ans;
- }
- ld FindS(ld r, ld h, ld g) {
- ld habs = abs(h);
- ld gabs = abs(g);
- ld S1 = S(r, habs, gabs);
- if (h >= 0 && g >= 0) {
- return S1;
- }
- ld kekg = S(r, gabs, 0) * 2;
- ld kekh = S(r, habs, 0) * 2;
- if (h < 0 && g < 0) {
- ld ans = PI * r * r - kekg - kekh + S1;
- return ans;
- } else if (g < 0) {
- return kekh - S1;
- } else {
- return kekg - S1;
- }
- }
- ld CrossCaH(ld X1, ld Y1, ld r1, ld X2, ld Y2, ld r2) {
- ld dx = X2 - X1;
- ld dy = Y2 - Y1;
- dx = abs(dx);
- if (dy + r2 <= 0) return CrossC(r1, r2, dx, dy);
- if (dy - r2 >= 0) return 0;
- if (dx + r2 < -r1) return 0;
- if (dx - r2 > r1) return 0;
- ld xleft, xright;
- {
- ld f = sqrtl(r2 * r2 - dy * dy);
- xleft = dx - f;
- xright = dx + f;
- }
- if (xleft >= -r1 && xright <= r1) {
- auto fy1 = [&] (ld x) {
- return -sqrtl(r1 * r1 - x * x);
- };
- auto fy2 = [&] (ld x) {
- return dy - sqrtl(r2 * r2 - (dx - x) * (dx - x));
- };
- auto f = [&] (ld x) {
- return fy2(x) - fy1(x);
- };
- ld mid1, mid2;
- for (int itr = 0; itr < 200; itr++) {
- mid1 = xleft + (xright - xleft) / 3;
- mid2 = xright - (xright - xleft) / 3;
- if (f(mid1) < f(mid2)) {
- xright = mid2;
- } else {
- xleft = mid1;
- }
- }
- if (f(xleft) > 0) {
- return FindS(r2, 0, dy) * 2;
- } else {
- return CrossC(r1, r2, dx, dy) - FindS(r2, 0, -dy) * 2;
- }
- }
- if (xleft <= -r1 && xright >= r1) {
- auto fy1 = [&] (ld x) {
- return sqrtl(r1 * r1 - x * x);
- };
- auto fy2 = [&] (ld x) {
- return dy + sqrtl(r2 * r2 - (dx - x) * (dx - x));
- };
- auto f = [&] (ld x) {
- return fy2(x) - fy1(x);
- };
- xleft = -r1;
- xright = r1;
- ld mid1, mid2;
- for (int itr = 0; itr < 200; itr++) {
- mid1 = xleft + (xright - xleft) / 3;
- mid2 = xright - (xright - xleft) / 3;
- if (f(mid1) <= f(mid2)) {
- xright = mid2;
- } else {
- xleft = mid1;
- }
- }
- if (f(xleft) < 0) {
- return PI * r1 * r1 / 2;
- } else {
- return CrossC(r1, r2, dx, dy) - PI * r1 * r1 / 2;
- }
- }
- {
- ld up, down;
- ld xmid;
- {
- // up
- xleft = dx - r2;
- xright = r1;
- auto fy1 = [&] (ld x) {
- return sqrtl(r1 * r1 - x * x);
- };
- auto fy2 = [&] (ld x) {
- return dy + sqrtl(r2 * r2 - (dx - x) * (dx - x));
- };
- for (int itr = 0; itr < 200; itr++) {
- xmid = (xleft + xright) / 2;
- if (fy1(xmid) < fy2(xmid)) {
- xright = xmid;
- } else {
- xleft = xmid;
- }
- }
- up = xleft;
- }
- {
- // down
- xleft = dx - r2;
- xright = r1;
- auto fy1 = [&] (ld x) {
- return -sqrtl(r1 * r1 - x * x);
- };
- auto fy2 = [&] (ld x) {
- return dy - sqrtl(r2 * r2 - (dx - x) * (dx - x));
- };
- for (int itr = 0; itr < 200; itr++) {
- xmid = (xleft + xright) / 2;
- if (fy1(xmid) < fy2(xmid)) {
- xleft = xmid;
- } else {
- xright = xmid;
- }
- }
- down = xleft;
- }
- if (up < down) {
- ld ans = FindS(r1, 0, down) + FindS(r2, dy, dx - down);
- return ans;
- } else {
- ld ans = CrossC(r1, r2, dx, dy) - FindS(r1, 0, up) - FindS(r2, -dy, dx - up);
- return ans;
- }
- }
- assert(false);
- }
- ld CrossHaH(ld x1, ld y1, ld x2, ld y2) {
- ld dx = x2 - x1;
- ld dy = y2 - y1;
- dy = abs(dy);
- dx = abs(dx);
- return CrossCaH(0, 0, 60, dx, dy, 60);
- }
- struct Smile {
- ld xmid = 0, ymid = 0;
- ld leftEyeX, leftEyeY = 0;
- ld rightEyeX = 0, rightEyeY = 0;
- ld mouthX = 0, mouthY = 0;
- const ld faceR = 100;
- const ld leftEyeR = 30;
- const ld rightEyeR = 30;
- const ld mouthR = 60;
- Smile(ld xmid, ld ymid) : xmid(xmid), ymid(ymid) {
- leftEyeX = xmid - 40;
- leftEyeY = ymid + 30;
- rightEyeX = xmid + 40;
- rightEyeY = ymid + 30;
- mouthX = xmid;
- mouthY = ymid - 20;
- }
- };
- int main() {
- ld x1, y1, x2, y2;
- cin >> x1 >> y1 >> x2 >> y2;
- Smile a(x1, y1);
- Smile b(x2, y2);
- ld ans = 0;
- ld dx = x2 - x1;
- ld dy = y2 - y1;
- ans += PI * a.faceR * a.faceR + PI * b.faceR * b.faceR - CrossC(a.faceR, b.faceR, dx, dy);
- ans -= PI * a.leftEyeR * a.leftEyeR - CrossC(a.leftEyeR, b.faceR, b.xmid - a.leftEyeX, b.ymid - a.leftEyeY);
- ans -= PI * a.rightEyeR * a.rightEyeR - CrossC(a.rightEyeR, b.faceR, b.xmid - a.rightEyeX, b.ymid - a.rightEyeY);
- ans -= PI * b.leftEyeR * b.leftEyeR - CrossC(b.leftEyeR, a.faceR, a.xmid - b.leftEyeX, a.ymid - b.leftEyeY);
- ans -= PI * b.rightEyeR * b.rightEyeR - CrossC(b.rightEyeR, a.faceR, a.xmid - b.rightEyeX, a.ymid - b.rightEyeY);
- ld cur1 = CrossCaH(a.mouthX, a.mouthY, a.mouthR, b.xmid, b.ymid, b.faceR);
- ld cur2 = CrossCaH(b.mouthX, b.mouthY, b.mouthR, a.xmid, a.ymid, a.faceR);
- cur1 = 0.5 * PI * a.mouthR * a.mouthR - cur1;
- cur2 = 0.5 * PI * b.mouthR * b.mouthR - cur2;
- ans -= cur1 + cur2;
- ans -= CrossC(a.leftEyeR, b.leftEyeR, a.leftEyeX - b.leftEyeX, a.leftEyeY - b.leftEyeY);
- ans -= CrossC(a.leftEyeR, b.rightEyeR, a.leftEyeX - b.rightEyeX, a.leftEyeY - b.rightEyeY);
- ans -= CrossC(a.rightEyeR, b.leftEyeR, a.rightEyeX - b.leftEyeX, a.rightEyeY - b.leftEyeY);
- ans -= CrossC(a.rightEyeR, b.rightEyeR, a.rightEyeX - b.rightEyeX, a.rightEyeY - b.rightEyeY);
- ans -= CrossCaH(a.mouthX, a.mouthY, a.mouthR, b.leftEyeX, b.leftEyeY, b.leftEyeR);
- ans -= CrossCaH(a.mouthX, a.mouthY, a.mouthR, b.rightEyeX, b.rightEyeY, b.rightEyeR);
- ans -= CrossCaH(b.mouthX, b.mouthY, b.mouthR, a.leftEyeX, a.leftEyeY, a.leftEyeR);
- ans -= CrossCaH(b.mouthX, b.mouthY, b.mouthR, a.rightEyeX, a.rightEyeY, a.rightEyeR);
- ld mm = CrossHaH(a.mouthX, a.mouthY, b.mouthX, b.mouthY);
- ans -= mm;
- cout << fixed << setprecision(15) << ans << '\n';
- }
Add Comment
Please, Sign In to add comment