111-111-111

Geometry Library

Jun 6th, 2020
386
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.99 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <iostream>
  4. #include <vector>
  5. #include <set>
  6. #include <unordered_set>
  7. #include <cmath>
  8. using namespace std;
  9. using ll = unsigned long long;
  10.  
  11.  
  12. #define MAX_SIZE 1000
  13. const double PI = 2.0*acos(0.0);
  14. const double EPS = 1e-9; //too small/big?????
  15. struct PT
  16. {
  17.     double x,y;
  18.     double length() {return sqrt(x*x+y*y);}
  19.     int normalize()
  20.     // normalize the vector to unit length; return -1 if the vector is 0
  21.     {
  22.         double l = length();
  23.         if(fabs(l)<EPS) return -1;
  24.         x/=l; y/=l;
  25.         return 0;
  26.     }
  27.     PT operator-(PT a)
  28.     {
  29.         PT r;
  30.         r.x=x-a.x; r.y=y-a.y;
  31.         return r;
  32.     }
  33.     PT operator+(PT a)
  34.     {
  35.         PT r;
  36.         r.x=x+a.x; r.y=y+a.y;
  37.         return r;
  38.     }
  39.     PT operator*(double sc)
  40.     {
  41.         PT r;
  42.         r.x=x*sc; r.y=y*sc;
  43.         return r;
  44.     }
  45. };
  46.  
  47. bool operator<(const PT& a,const PT& b)
  48. {
  49.     if(fabs(a.x-b.x)<EPS) return a.y<b.y;
  50.     return a.x<b.x;
  51. }
  52. double dist(PT& a, PT& b)
  53. // the distance between two points
  54. {
  55.     return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
  56. }
  57. double dot(PT& a, PT& b)
  58. // the inner product of two vectors
  59. {
  60.     return(a.x*b.x+a.y*b.y);
  61. }
  62.  
  63. // ==========================================================
  64. // The Convex Hull
  65. // ==========================================================
  66. int sideSign(PT& p1,PT& p2,PT& p3)
  67. // which side is p3 to the line p1->p2? returns: 1 left, 0 on, -1 right
  68. {
  69.     double sg = (p1.x-p3.x)*(p2.y-p3.y)-(p1.y - p3.y)*(p2.x-p3.x);
  70.     if(fabs(sg)<EPS) return 0;
  71.     if(sg>0)return 1;
  72.     return -1;
  73. }
  74. // To find orientation of ordered triplet (p1, p2, p3).
  75. // The function returns following values
  76. bool better(PT& p1,PT& p2,PT& p3)
  77. // used by convec hull: from p3, if p1 is better than p2
  78. {
  79.     double sg = (p1.y - p3.y)*(p2.x-p3.x)-(p1.x-p3.x)*(p2.y-p3.y);
  80.     //watch range of the numbers
  81.     if(fabs(sg)<EPS)
  82.     {
  83.         if(dist(p3,p1)>dist(p3,p2))return true;
  84.         else return false;
  85.     }
  86.     if(sg<0) return true;
  87.     return false;
  88. }
  89.  
  90. //convex hull in n*n
  91. void vex(vector<PT>& vin,vector<PT>& vout)
  92. {
  93.     vout.clear();
  94.     int n=vin.size();
  95.     int st=0;
  96.     int i;
  97.     for(i=1;i<n;i++) if(vin[i]<vin[st]) st=i;
  98.     vector<int> used;
  99.     // used[i] is the index of the i-th point on the hull
  100.     used.push_back(st);
  101.     int idx=st; int next;
  102.     do{
  103.         next=0;
  104.         for(i=1;i<n;i++)
  105.             if(better(vin[i],vin[next],vin[idx]))next=i;
  106.         idx=next;
  107.         used.push_back(idx);
  108.     }while(idx!=st);
  109.     for(i=0;i+1<used.size();i++) vout.push_back(vin[used[i]]);
  110. }
  111. //convex hull nlogn
  112. void vex2(vector<PT> vin,vector<PT>& vout)
  113. // vin is not pass by reference, since we will rotate it
  114. {
  115.     vout.clear();
  116.     int n=vin.size();
  117.     sort(vin.begin(),vin.end());
  118.     PT stk[MAX_SIZE];
  119.     int pstk, i;
  120.     // hopefully more than 2 points
  121.     stk[0] = vin[0];
  122.     stk[1] = vin[1];
  123.     pstk = 2;
  124.     for(i=2; i<n; i++)
  125.     {
  126.         if(dist(vin[i], vin[i-1])<EPS) continue;
  127.         while(pstk > 1 && better(vin[i], stk[pstk-1], stk[pstk-2]))
  128.             pstk--;
  129.         stk[pstk] = vin[i];
  130.         pstk++;
  131.     }
  132.     for(i=0; i<pstk; i++) vout.push_back(stk[i]);
  133.     // turn 180 degree
  134.     for(i=0; i<n; i++)
  135.     {
  136.         vin[i].y = -vin[i].y;
  137.         vin[i].x = -vin[i].x;
  138.     }
  139.     sort(vin.begin(), vin.end());
  140.     stk[0] = vin[0];
  141.     stk[1] = vin[1];
  142.     pstk = 2;
  143.     for(i=2; i<n; i++)
  144.     {
  145.         if(dist(vin[i], vin[i-1])<EPS) continue;
  146.         while(pstk > 1 && better(vin[i], stk[pstk-1], stk[pstk-2]))
  147.             pstk--;
  148.         stk[pstk] = vin[i];
  149.         pstk++;
  150.     }
  151.     for(i=1; i<pstk-1; i++)
  152.     {
  153.         stk[i].x= -stk[i].x; // don’t forget rotate 180 d back.
  154.         stk[i].y= -stk[i].y;
  155.         vout.push_back(stk[i]);
  156.     }
  157. }
  158. int isConvex(vector<PT>& v)
  159. // test whether a simple polygon is convex
  160. // return 0 if not convex, 1 if strictly convex,
  161. // 2 if convex but there are points unnecesary
  162. // this function does not work if the polycon is self intersecting
  163. // in that case, compute the convex hull of v, and see if both have the same area
  164. {
  165.     int i,j,k;
  166.     int c1=0; int c2=0; int c0=0;
  167.     int n=v.size();
  168.     for(i=0;i<n;i++)
  169.     {
  170.         j=(i+1)%n;
  171.         k=(j+1)%n;
  172.         int s=sideSign(v[i], v[j], v[k]);
  173.         if(s==0) c0++;
  174.         if(s>0) c1++;
  175.         if(s<0) c2++;
  176.     }
  177.     if(c1 && c2) return 0;
  178.     if(c0) return 2;
  179.     return 1;
  180. }
  181.  
  182. // ==========================================================
  183. // Areas
  184. // ==========================================================
  185. double trap(PT a, PT b)
  186. {
  187.     return (0.5*(b.x - a.x)*(b.y + a.y));
  188. }
  189. double area(vector<PT> &vin)
  190. // Area of a simple polygon, not neccessary convex
  191. {
  192.     int n = vin.size();
  193.     double ret = 0.0;
  194.     for(int i = 0; i < n; i++)
  195.         ret += trap(vin[i], vin[(i+1)%n]);
  196.     return fabs(ret);
  197. }
  198. double peri(vector<PT> &vin)
  199. // Perimeter of a simple polygon, not neccessary convex
  200. {
  201.     int n = vin.size();
  202.     double ret = 0.0;
  203.     for(int i = 0; i < n; i++)
  204.         ret += dist(vin[i], vin[(i+1)%n]);
  205.     return ret;
  206. }
  207. // Given three colinear points p, q, r, the function checks if
  208. double triarea(PT a, PT b, PT c)
  209. {
  210.     return fabs(trap(a,b)+trap(b,c)+trap(c,a));
  211. }
  212. double height(PT a, PT b, PT c)
  213. // height from a to the line bc
  214. {
  215.     double s3 = dist(c, b);
  216.     double ar=triarea(a,b,c);
  217.     return(2.0*ar/s3);
  218. }
  219. // ====================================================
  220. // Points and Lines
  221. // ====================================================
  222. int intersection( PT p1, PT p2, PT p3, PT p4, PT &r )
  223. // two lines given by p1->p2, p3->p4 r is the intersection point
  224. // return -1 if two lines are parallel
  225. {
  226.     double d = (p4.y - p3.y)*(p2.x-p1.x) - (p4.x - p3.x)*(p2.y - p1.y);
  227.     if( fabs( d ) < EPS ) return -1;
  228.     // might need to do something special!!!
  229.     double ua, ub;
  230.     ua = (p4.x - p3.x)*(p1.y-p3.y) - (p4.y-p3.y)*(p1.x-p3.x);
  231.     ua /= d;
  232.     // ub = (p2.x - p1.x)*(p1.y-p3.y) - (p2.y-p1.y)*(p1.x-p3.x);
  233.     //ub /= d;
  234.     r = p1 + (p2-p1)*ua;
  235.     return 0;
  236. }
  237. void closestpt( PT p1, PT p2, PT p3, PT &r )
  238. // the closest point on the line p1->p2 to p3
  239. {
  240.     if( fabs( triarea( p1, p2, p3 ) ) < EPS )
  241.     { r = p3; return; }
  242.     PT v = p2-p1;
  243.     v.normalize();
  244.     double pr; // inner product
  245.     pr = (p3.y-p1.y)*v.y + (p3.x-p1.x)*v.x;
  246.     r = p1+v*pr;
  247. }
  248. int hcenter( PT p1, PT p2, PT p3, PT& r )
  249. {
  250.     // point generated by altitudes
  251.     if( triarea( p1, p2, p3 ) < EPS ) return -1;
  252.     PT a1, a2;
  253.     closestpt( p2, p3, p1, a1 );
  254.     closestpt( p1, p3, p2, a2 );
  255.     intersection( p1, a1, p2, a2, r );
  256.     return 0;
  257. }
  258. int center( PT p1, PT p2, PT p3, PT& r )
  259. {
  260.     // point generated by circumscribed circle
  261.     if( triarea( p1, p2, p3 ) < EPS ) return -1;
  262.     PT a1, a2, b1, b2;
  263.     a1 = (p2+p3)*0.5;
  264.     a2 = (p1+p3)*0.5;
  265.     b1.x = a1.x - (p3.y-p2.y);
  266.     b1.y = a1.y + (p3.x-p2.x);
  267.     b2.x = a2.x - (p3.y-p1.y);
  268.     b2.y = a2.y + (p3.x-p1.x);
  269.     intersection( a1, b1, a2, b2, r );
  270.     return 0;
  271. }
  272.  
  273. int bcenter( PT p1, PT p2, PT p3, PT& r )
  274. {
  275.     // angle bisection
  276.     if( triarea( p1, p2, p3 ) < EPS ) return -1;
  277.     double s1, s2, s3;
  278.     s1 = dist( p2, p3 );
  279.     s2 = dist( p1, p3 );
  280.     s3 = dist( p1, p2 );
  281.     double rt = s2/(s2+s3);
  282.     PT a1,a2;
  283.     a1 = p2*rt+p3*(1.0-rt);
  284.     rt = s1/(s1+s3);
  285.     a2 = p1*rt+p3*(1.0-rt);
  286.     intersection( a1,p1, a2,p2, r );
  287.     return 0;
  288. }
  289. // ===============================================
  290. // Angles
  291. // ===============================================
  292. double angle(PT& p1, PT& p2, PT& p3)
  293. // angle from p1->p2 to p1->p3, returns -PI to PI
  294. {
  295.     PT va = p2-p1;
  296.     va.normalize();
  297.     PT vb; vb.x=-va.y; vb.y=va.x;
  298.     PT v = p3-p1;
  299.     double x,y;
  300.     x=dot(v, va);
  301.     y=dot(v, vb);
  302.     return(atan2(y,x));
  303. }
  304. double angle(double a, double b, double c)
  305. // in a triangle with sides a,b,c, the angle between b and c
  306. // we do not check if a,b,c is a triangle here
  307. {
  308.     double cs=(b*b+c*c-a*a)/(2.0*b*c);
  309.     return(acos(cs));
  310. }
  311. void rotate(PT p0, PT p1, double a, PT& r)
  312. // rotate p1 around p0 clockwise, by angle a
  313. // don’t pass by reference for p1, so r and p1 can be the same
  314. {
  315.     p1 = p1-p0;
  316.     r.x = cos(a)*p1.x-sin(a)*p1.y;
  317.     r.y = sin(a)*p1.x+cos(a)*p1.y;
  318.     r = r+p0;
  319. }
  320. void reflect(PT& p1, PT& p2, PT p3, PT& r)
  321. // p1->p2 line, reflect p3 to get r.
  322. {
  323.     if(dist(p1, p3)<EPS) {r=p3; return;}
  324.     double a=angle(p1, p2, p3);
  325.     r=p3;
  326.     rotate(p1, r, -2.0*a, r);
  327. }
  328. // ===============================================
  329. // points, lines, and circles
  330. // ===============================================
  331. int pAndSeg(PT& p1, PT& p2, PT& p)
  332. // the relation of the point p and the segment p1->p2.
  333. // 1 if point is on the segment; 0 if not on the line; -1 if on the line but not on the segment
  334. {
  335.     double s=triarea(p, p1, p2);
  336.     if(s>EPS) return(0);
  337.     double sg=(p.x-p1.x)*(p.x-p2.x);
  338.     if(sg>EPS) return(-1);
  339.     sg=(p.y-p1.y)*(p.y-p2.y);
  340.     if(sg>EPS) return(-1);
  341.     return(1);
  342. }
  343. int lineAndCircle(PT& oo, double r, PT& p1, PT& p2, PT& r1, PT& r2)
  344. // returns -1 if there is no intersection
  345. // returns 1 if there is only one intersection
  346. {
  347.     PT m;
  348.     closestpt(p1,p2,oo,m);
  349.     PT v = p2-p1;
  350.     v.normalize();
  351.     double r0=dist(oo, m);
  352.     if(r0>r+EPS) return -1;
  353.     if(fabs(r0-r)<EPS)
  354.     {
  355.         r1=r2=m;
  356.         return 1;
  357.     }
  358.     double dd = sqrt(r*r-r0*r0);
  359.     r1 = m-v*dd; r2 = m+v*dd;
  360.     return 0;
  361. }
  362.  
  363. int CAndC(PT o1, double r1, PT o2, double r2, PT& q1, PT& q2)
  364. // intersection of two circles
  365. // -1 if no intersection or infinite intersection
  366. // 1 if only one point
  367. {
  368.     double r=dist(o1,o2);
  369.     if(r1<r2) { swap(o1,o2); swap(r1,r2); }
  370.     if(r<EPS) return(-1);
  371.     if(r>r1+r2+EPS) return(-1);
  372.     if(r<r1-r2-EPS) return(-1);
  373.     PT v = o2-o1; v.normalize();
  374.     q1 = o1+v*r1;
  375.     if(fabs(r-r1-r2)<EPS || fabs(r+r2-r1)<EPS)
  376.     { q2=q1; return(1); }
  377.     double a=angle(r2, r, r1);
  378.     q2=q1;
  379.     rotate(o1, q1, a, q1);
  380.     rotate(o1, q2, -a, q2);
  381.     return 0;
  382. }
  383. int pAndPoly(vector<PT> pv, PT p)
  384. // the relation of the point and the simple polygon
  385. // 1 if p is in pv; 0 outside; -1 on the polygon
  386. {
  387.     int i, j;
  388.     int n=pv.size();
  389.     pv.push_back(pv[0]);
  390.     for(i=0;i<n;i++)
  391.         if(pAndSeg(pv[i], pv[i+1], p)==1) return(-1);
  392.     for(i=0;i<n;i++)
  393.         pv[i] = pv[i]-p;
  394.     p.x=p.y=0.0;
  395.     double a, y;
  396.     while(1)
  397.     {
  398.         a=(double)rand()/10000.00;
  399.         j=0;
  400.         for(i=0;i<n;i++)
  401.         {
  402.             rotate(p, pv[i], a, pv[i]);
  403.             if(fabs(pv[i].x)<EPS) j=1;
  404.         }
  405.         if(j==0)
  406.         {
  407.             pv[n]=pv[0];
  408.             j=0;
  409.             for(i=0;i<n;i++) if(pv[i].x*pv[i+1].x < -EPS)
  410.             {
  411.                 y=pv[i+1].y-pv[i+1].x*(pv[i].y-pv[i+1].y)/(pv[i].x-pv[i+1].x);
  412.                 if(y>0) j++;
  413.             }
  414.             return(j%2);
  415.         }
  416.     }
  417.     return 1;
  418. }
  419. void show(PT& p)
  420. {
  421.     cout<<"("<<p.x<<", "<<p.y<<")"<<endl;
  422. }
  423. void show(vector<PT>& p)
  424. {
  425.     int i,n=p.size();
  426.     for(i=0;i<n;i++) show(p[i]);
  427.     cout<<":)"<<endl;
  428. }
  429. void cutPoly(vector<PT>& pol, PT& p1, PT& p2, vector<PT>& pol1, vector<PT>& pol2)
  430. // cut the convex polygon pol along line p1->p2;
  431. // pol1 are the resulting polygon on the left side, pol2 on the right.
  432. {
  433.     vector<PT> pp,pn;
  434.     pp.clear(); pn.clear();
  435.     int i, sg, n=pol.size();
  436.     PT q1,q2,r;
  437.     for(i=0;i<n;i++)
  438.     {
  439.         q1=pol[i]; q2=pol[(i+1)%n];
  440.         sg=sideSign(p1, p2, q1);
  441.         if(sg>=0) pp.push_back(q1);
  442.         if(sg<=0) pn.push_back(q1);
  443.         if(intersection(p1, p2, q1, q2,r)>=0)
  444.         {
  445.             if(pAndSeg(q1, q2, r)==1)
  446.             {
  447.                 pp.push_back(r);
  448.                 pn.push_back(r);
  449.             }
  450.         }
  451.     }
  452.     pol1.clear(); pol2.clear();
  453.     if(pp.size()>2) vex2(pp, pol1);
  454.     if(pn.size()>2) vex2(pn, pol2);
  455.     //show(pol1);
  456.     //show(pol2);
  457. }
  458.    
  459.    
  460. int main() {
  461.     ios_base::sync_with_stdio(false);
  462.  
  463.     return 0;
  464. }
Add Comment
Please, Sign In to add comment