Advertisement
cincout

Geometry

Mar 29th, 2019
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.13 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. typedef long long ll;
  3. typedef long double ld;
  4. using namespace std;
  5.  
  6. namespace geoma {
  7. #define Doub ld
  8. #define Long ll
  9. #define Fix cout << fixed << setprecision(10)
  10. const long double Pi = acos(-1);
  11. const long double Eps = 1e-8;
  12. const Long magic = -2423423324;
  13. bool is_equal(Doub a, Doub b) {
  14. return fabs(a - b) < Eps;
  15. }
  16. struct line {
  17. Doub A, B, C;
  18. line() {
  19. A = B = C = 0;
  20. }
  21. line(Doub _A, Doub _B, Doub _C) {
  22. A = _A, B = _B, C = _C;
  23. }
  24. Doub get_y(Doub &x) {
  25. if (B == 0) {
  26. return 0;
  27. }
  28. return (-C - A * x) / B;
  29. }
  30. Doub get_x(Doub &y) {
  31. if (A == 0) {
  32. return 0;
  33. }
  34. return (-C - B * y) / A;
  35. }
  36. void normalize() {
  37. auto opr = hypot(A, B);
  38. A /= opr, B /= opr, C /= opr;
  39. }
  40. bool operator == (const line &other) {
  41. return A == other.A && B == other.B && C == other.C;
  42. }
  43. };
  44. istream& operator >> (istream& in, line &t) { return in >> t.A >> t.B >> t.C; }
  45. ostream& operator << (ostream& out, line t) { Fix; return out << t.A << ' ' << t.B << ' ' << t.C; }
  46. struct point {
  47. Doub x, y;
  48. point() {
  49. x = y = 0;
  50. }
  51. point(Doub _x, Doub _y) {
  52. x = _x, y = _y;
  53. }
  54. Long operator * (point other) {
  55. return x * other.y - other.x * y;
  56. }
  57. Long operator ^ (point other) {
  58. return x * other.x + y * other.y;
  59. }
  60. point operator- (point other) {
  61. return {x - other.x, y - other.y};
  62. }
  63. point operator+ (point other) {
  64. return {x + other.x, y + other.y};
  65. }
  66. point operator*(Long k) {
  67. return {x * k, y * k};
  68. }
  69. point operator*(Doub k) {
  70. return {x * k, y * k};
  71. }
  72. void operator+= (point b) {
  73. x += b.x;
  74. y += b.y;
  75. }
  76. void operator-= (point b) {
  77. x -= b.x;
  78. y -= b.y;
  79. }
  80. Doub len() {
  81. return sqrt(1.0*(x * x + y * y));
  82. }
  83. Long klen() {
  84. return x * x + y * y;
  85. }
  86. bool operator == (const point &other) {
  87. return x == other.x && y == other.y;
  88. }
  89. Doub dist_to_line(line t) {
  90. t.normalize();
  91. return t.A * x + t.B * y + t.C;
  92. }
  93. Doub ang1(const point &b) { // [0..pi]
  94. point a = (*this);
  95. Doub num = a * b;
  96. Doub den = a ^ b;
  97. if (num == 0 && den > 0)
  98. return 0;
  99. ld ret = fabs(atan2(num, den));
  100. if (ret == 0) {
  101. ret = Pi;
  102. }
  103. return ret;
  104. }
  105. Doub ang2(const point &b) { // [-pi..pi]
  106. point a = (*this);
  107. Doub num = a * b;
  108. Doub den = a ^ b;
  109. return atan2(num, den);
  110. }
  111. bool is_lie(line t) {
  112. return is_equal(t.A * x + t.B * y + t.C, 0);
  113. }
  114. point projection(line t) {
  115. t.normalize();
  116. auto len = dist_to_line(t);
  117. point ret = (*this);
  118. point ve(t.A, t.B);
  119. ret -= ve * len;
  120. bool inv = is_lie(t);
  121. //assert(inv);
  122. return ret;
  123. }
  124. void normalize() {
  125. auto op = hypot(x, y);
  126. x /= op, y /= op;
  127. }
  128. };
  129. istream& operator >> (istream& in, point &t) { return in >> t.x >> t.y; }
  130. ostream& operator << (ostream& out, point t) { Fix; return out << t.x << ' ' << t.y; }
  131. line toline(const point &a, const point &b) {
  132. line ret;
  133. ret.A = a.y - b.y; ret.B = b.x - a.x; ret.C = a.x * b.y - b.x * a.y;
  134. return ret;
  135. }
  136. struct circle {
  137. point C;
  138. Doub R;
  139. auto cross_with_line(line x) {
  140. auto t = (*this);
  141. auto d = fabs(t.C.dist_to_line(x));
  142. vector <point> ans;
  143. if (d > t.R)
  144. return ans;
  145. x.normalize();
  146. point ve(x.A, x.B);
  147. Doub len = ve.len();
  148. point var_1 = t.C; var_1 += ve * d;
  149. point var_2 = t.C; var_2 -= ve * d;
  150. auto len_var_1 = fabs(var_1.dist_to_line(x));
  151. auto len_var_2 = fabs(var_2.dist_to_line(x));
  152. if (len_var_1 > len_var_2)
  153. swap(var_1, var_2);
  154. if (is_equal(d, t.R)) {
  155. x.normalize();
  156. ans.push_back(var_1);
  157. return ans;
  158. }
  159. if (is_equal(d, 0)) {
  160. x.normalize();
  161. point ve1 = {-x.B, x.A};
  162. auto ans1 = t.C;
  163. ans1 += ve1 * t.R;
  164. ans.push_back(ans1);
  165. ans1 = t.C;
  166. ans1 -= ve1 * t.R;
  167. ans.push_back(ans1);
  168. return ans;
  169. }
  170. Doub k1 = hypot(t.R, len);
  171. auto ve1 = var_1 - t.C;
  172. ve1 = {-ve1.y, ve1.x};
  173. len = ve1.len() * 2;
  174. point ans1 = {var_1.x + ve1.x * k1 / len , var_1.y + ve1.y * k1 / len};
  175. point ans2 = {var_1.x - ve1.x * k1 / len , var_1.y - ve1.y * k1 / len};
  176. ans.push_back(ans1), ans.push_back(ans2);
  177. return ans;
  178. }
  179. auto cross_with_circle(circle b) {
  180. circle a = (*this);
  181. vector <point> ret;
  182. if (a.C == b.C) {
  183. if (a.R == b.R) {
  184. point clu(-2423423324, -42342423);
  185. ret.push_back(clu);
  186. }
  187. return ret;
  188. }
  189. auto l = (a.C - b.C).len();
  190. Doub v[3];
  191. v[0] = a.R;
  192. v[1] = b.R;
  193. v[2] = l;
  194. sort(v, v + 3);
  195. if (v[0] + v[1] < v[2]) {
  196. return ret;
  197. }
  198. if (v[0] + v[1] == v[2]) {
  199. point ans;
  200. ans = a.C;
  201. auto ve = b.C - a.C;
  202. ve.normalize();
  203. ans = a.C;
  204. ans.x += ve.x * (a.R + b.R);
  205. ans.y += ve.y * (a.R + b.R);
  206. if (ans == b.C) {
  207. ans.x -= ve.x * b.R;
  208. ans.y -= ve.y * b.R;
  209. ret.push_back(ans);
  210. return ret;
  211. }
  212. else {
  213. ans = a.C;
  214. ans.x += ve.x * (a.R - b.R);
  215. ans.y += ve.y * (a.R - b.R);
  216. if (ans == b.C) {
  217. ans = a.C;
  218. ans.x += ve.x * a.R;
  219. ans.y += ve.y * a.R;
  220. ret.push_back(ans);
  221. return ret;
  222. }
  223. else {
  224. swap(a, b);
  225. ans = a.C;
  226. ve = b.C - a.C;
  227. ve.normalize();
  228. ans.x += ve.x * a.R;
  229. ans.y += ve.y * a.R;
  230. ret.push_back(ans);
  231. return ret;
  232. }
  233. }
  234. }
  235. else {
  236. Doub r2 = b.R;
  237. Doub r1 = a.R;
  238. Doub cos = (l*l + r2*r2 - r1*r1) / (2 * l * r2);
  239. Doub O2H = r2 * cos;
  240. Doub PH = sqrt(r2 * r2 - O2H * O2H);
  241. point H = b.C;
  242. auto ve = a.C - b.C;
  243. ve.normalize();
  244. H.x = H.x + ve.x * O2H;
  245. H.y = H.y + ve.y * O2H;
  246. auto ln = toline(b.C, a.C);
  247. ln.normalize();
  248. point ans1 = H;
  249. ans1.x = ans1.x + ln.A * PH;
  250. ans1.y = ans1.y + ln.B * PH;
  251. point ans2 = H;
  252. ans2.x = ans2.x - ln.A * PH;
  253. ans2.y = ans2.y - ln.B * PH;
  254. ret.push_back(ans1), ret.push_back(ans2);
  255. return ret;
  256. }
  257. }
  258. };
  259. istream &operator >> (istream &in, circle &t) { return in >> t.C >> t.R; }
  260. point inter(line fi, line se) {
  261. Doub y = (se.A * fi.C - fi.A * se.C) / (fi.A * se.B - se.A * fi.B);
  262. Doub x;
  263. if (fi.A != 0)
  264. x = fi.get_x(y);
  265. else
  266. x = se.get_x(y);
  267. return {x, y};
  268. }
  269. struct segment {
  270. point begin, end;
  271. bool is_beetwen(point a) {
  272. if (a == begin || a == end)
  273. return 1;
  274. return (((end - begin) * (a - begin) == 0) && (((begin - a) ^ (end - a)) <= 0));
  275. }
  276. bool is_cross(segment b) {
  277. auto a1 = begin, a2 = end, b1 = b.begin, b2 = b.end;
  278. if ((a2 - a1) * (b2 - b1) == 0) {
  279. ll sc = (a2 - a1) * (b2 - a1);
  280. if (sc != 0) return 0;
  281. return (b.is_beetwen(a1) || b.is_beetwen(a2) || segment {a1, a2}.is_beetwen(b1) || segment {a1, a2}.is_beetwen(b2));
  282. }
  283. else {
  284. return ((((a2 - a1) * (b2 - a1)) * ((a2 - a1) * (b1 - a1)) <= 0) && (((b1 - b2) * (a1 - b2)) * ((b1 - b2) * (a2 - b2)) <= 0));
  285. }
  286. }
  287. Doub dist_to_point(point s) {
  288. point get = s.projection(toline(begin, end));
  289. segment c;
  290. c.begin = begin, c.end = end;
  291. if (c.is_beetwen(get)) {
  292. return s.dist_to_line(toline(begin, end));
  293. }
  294. else {
  295. return min((s - begin).len(), (s - end).len());
  296. }
  297. }
  298. Doub len() {
  299. return (end - begin).len();
  300. }
  301. Doub dist_to_segment(segment b) {
  302. segment a = (*this);
  303. Doub ans;
  304. if (a.len() == 1 && b.len() == 1) {
  305. ans = (a.begin - b.begin).len();
  306. }
  307. else if (a.len() == 1) {
  308. ans = fabs(b.dist_to_point(a.begin));
  309. }
  310. else if (b.len() == 1) {
  311. ans = fabs(a.dist_to_point(b.begin));
  312. }
  313. else {
  314. if (a.is_cross(b)) {
  315. ans = 0;
  316. }
  317. else {
  318. ans = fabs(a.dist_to_point(b.begin));
  319. ans = min(ans, fabs(a.dist_to_point(b.end)));
  320. ans = min(ans, fabs(b.dist_to_point(a.begin)));
  321. ans = min(ans, fabs(b.dist_to_point(a.end)));
  322. }
  323. }
  324. return ans;
  325. }
  326. bool is_point_on_ray(point a) {
  327. auto b = begin;
  328. auto c = end;
  329. return ((((a - b) ^ (c - b)) >= 0 && ((a - b)*(c - b)) == 0));
  330. }
  331. Doub dist_to_ray(segment b) {
  332. auto a = (*this);
  333. if (b.is_point_on_ray(a.begin) || b.is_point_on_ray(a.end)|| a.is_point_on_ray(b.begin) || a.is_point_on_ray(b.end)) {
  334. return 0;
  335. }
  336.  
  337. ld ans = a.dist_to_segment(b);
  338.  
  339. line fi = toline(a.begin, a.end);
  340. line se = toline(b.begin, b.end);
  341. auto teta = inter(fi, se);
  342.  
  343. bool parallel = (((a.end - a.begin) ^ (b.end - b.begin)) == 0);
  344.  
  345. if (!parallel && b.is_point_on_ray(teta)&& a.is_point_on_ray(teta)) {
  346. ans = 0;
  347. }
  348.  
  349. // работаем с a
  350. auto T = a.begin.projection(se);
  351. if ( b.is_point_on_ray(T))
  352. ans = min(ans, fabs(a.begin.dist_to_line(se)));
  353. T = a.end.projection(se);
  354. if (b.is_point_on_ray(T))
  355. ans = min(ans, fabs(a.end.dist_to_line(se)));
  356.  
  357. // работаем с b
  358. T = b.begin.projection(fi);
  359. if (a.is_point_on_ray(T))
  360. ans = min(ans, fabs(b.begin.dist_to_line(fi)));
  361. T = b.end.projection(fi);
  362. if (a.is_point_on_ray(T))
  363. ans = min(ans, fabs(b.end.dist_to_line(fi)));
  364. return ans;
  365. }
  366. };
  367. istream& operator >> (istream& in, segment &t) { return in >> t.begin >> t.end; }
  368. int sign(int a) {
  369. if (a == 0)
  370. return 0;
  371. if (a < 0)
  372. return -1;
  373. return 1;
  374. }
  375. bool in_ang(point a, point o, point b, point c) { // aob - угол
  376. if (segment {c, o}.is_beetwen(b)) return 1;
  377. if (segment {c, o}.is_beetwen(a)) return 1;
  378. ll t1 = (b - o) * (c - o);
  379. ll t2 = (c - o) * (a - o);
  380. ll t3 = (b - o) * (a - o);
  381. return sign(t1) == sign(t2) && sign(t2) == sign(t3);
  382. }
  383. struct polygon {
  384. vector <point> a;
  385. Doub square() {
  386. Doub res = 0;
  387. for (unsigned i = 0; i < a.size(); i++) {
  388. point
  389. p1 = i ? a[i - 1] : a.back(),
  390. p2 = a[i];
  391. res += (p1.x - p2.x) * (p1.y + p2.y);
  392. }
  393. return fabs(res) / 2;
  394. }
  395. bool in_polygon(point c) {
  396. int n = a.size();
  397. auto z = a[0];
  398. int l = 1, r = n - 2;
  399. if (!in_ang(a[l], z, a[n - 1], c)) {
  400. return 0;
  401. }
  402. while (r - l > 1) {
  403. int mid = (l + r) / 2;
  404. if (in_ang(a[mid], z, a[n - 1], c))
  405. l = mid;
  406. else
  407. r = mid;
  408. }
  409. r = l + 1;
  410. return (in_ang(a[l], z, a[r], c) && in_ang(a[l], a[r], z, c));
  411. }
  412. };
  413. bool cmph(point a, point b) {
  414. if (a.y != b.y)
  415. return a.y < b.y;
  416. return a.x < b.x;
  417. }
  418. bool ch_cmp(point a, point b) {
  419. if ((a * b) == 0) {
  420. return a.klen() < b.klen();
  421. }
  422. return (a * b) > 0;
  423. }
  424. auto convex_hull(polygon a) {
  425. point po(1e18, 1e18);
  426. point fi = *min_element(a.a.begin(), a.a.end(), cmph);
  427. for (auto &i : a.a)
  428. i -= fi;
  429. sort(a.a.begin(), a.a.end(), ch_cmp);
  430. vector <point> hull;
  431. hull.push_back(a.a[0]);
  432. for (int i = 1; i < a.a.size(); ++i) {
  433. while (hull.size() > 1 && ((a.a[i] - hull.back()) * (hull[hull.size() - 2] - hull.back())) <= 0) {
  434. hull.pop_back();
  435. }
  436. hull.push_back(a.a[i]);
  437. }
  438. for (auto &i : hull)
  439. i += po;
  440. return hull;
  441. }
  442. bool in_circle(point p, circle c) {
  443. return (c.C - p).len() < c.R;
  444. }
  445. auto tangent(circle a, point b) {
  446. ld AO = (a.C - b).len();
  447. vector <point> ret;
  448. if (AO == a.R) {
  449. ret.push_back({b.x, b.y});
  450. return ret;
  451. }
  452. if (AO < a.R) {
  453. return ret;
  454. }
  455. ld OD = a.R;
  456. ld AD = sqrt(AO * AO - OD * OD);
  457. ld CD = AD * OD / AO;
  458. ld OC = sqrt(OD * OD - CD * CD);
  459. point vec = b - a.C;
  460. auto cur = a.C;
  461. cur.x += (vec.x * OC / AO);
  462. cur.y += (vec.y * OC / AO);
  463. point vec2 = {-vec.y, vec.x};
  464. auto p1 = cur;
  465. p1.x += vec2.x * CD / AO;
  466. p1.y += vec2.y * CD / AO;
  467. auto p2 = cur;
  468. p2.x -= vec2.x * CD / AO;
  469. p2.y -= vec2.y * CD / AO;
  470. ret.push_back(p1);
  471. ret.push_back(p2);
  472. return ret;
  473. }
  474. line bisector(point x, point y, point z) {
  475. if (x.x == y.x && x.x == z.x) {
  476. auto ans = toline(x, {x.x + 1, x.y});
  477. return ans;
  478. }
  479. if (x.y == y.y && x.y == z.y) {
  480. auto ans = toline(x, {x.x, x.y + 1});
  481. cout << fixed << setprecision(10) << ans.A << ' ' << ans.B << ' ' << ans.C << '\n';
  482. exit(0);
  483. }
  484. auto v1 = y - x;
  485. v1.normalize();
  486. auto v2 = z - x;
  487. v2.normalize();
  488. auto t = x;
  489. t += v1;
  490. auto g = x;
  491. g += v2;
  492. auto ans = toline(x, {(g.x + t.x) / 2, (g.y + t.y) / 2});
  493. return ans;
  494. }
  495. };
  496.  
  497. using namespace geoma;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement