Advertisement
Kaidul

Computational Geometry Template

May 18th, 2013
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.85 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <map>
  5. #include <stack>
  6. #include <set>
  7. #include <list>
  8. #include <vector>
  9. #include <algorithm>
  10. #include <cassert>
  11. #include <iterator>
  12. #include <sstream>
  13. #include <complex>
  14. #include <bitset>
  15. #include <iomanip>
  16. #include <cctype>
  17. #include <limits>
  18. #include <numeric>
  19. #include <cmath>
  20. #include <functional>
  21. #include <queue>
  22. using namespace std;
  23.  
  24. #define pf printf
  25.  
  26. /**  স্থানাঙ্ক জ্যামিতি **/
  27.  
  28. // বিন্দু  - স্থানাঙ্ক (x, y)
  29. template< typename T >
  30. struct Point {
  31.     T x;
  32.     T y;
  33.  
  34.     Point(T xx, T yy) : x(xx), y(yy) {}
  35.     Point() : x(), y() {}
  36. };
  37.  
  38.  
  39. // স্থানাঙ্ক lhs(x, y) এবং rhs(x, y) এর জন্য অপারেটর ওভারলোডিং :
  40.  
  41. // minus
  42. template<typename T>
  43. Point<T> operator-( const Point<T>& lhs, const Point<T>& rhs) {
  44.     Point<T> ret( lhs.x - rhs.x, lhs.y - rhs.y);
  45.     return ret;
  46. }
  47.  
  48. // plus
  49. template<typename T>
  50. Point<T> operator+( const Point<T>& lhs, const Point<T>& rhs) {
  51.     Point<T> ret( lhs.x + rhs.x, lhs.y + rhs.y);
  52.     return ret;
  53. }
  54.  
  55. // equal to
  56. template<typename T>
  57. bool operator==( const Point<T>& lhs, const Point<T>& rhs) {
  58.     return lhs.x == rhs.x && lhs.y == rhs.y;
  59. }
  60.  
  61. // not equal to
  62. template<typename T>
  63. bool operator!=( const Point<T>& lhs, const Point<T>& rhs) {
  64.     return lhs.x != rhs.x || lhs.y != rhs.y;
  65. }
  66.  
  67. // division
  68. template<typename T>
  69. Point<T> operator/( const Point<T>& lhs, const T&  rhs) {
  70.     Point<T> ret( lhs.x / rhs, lhs.y / rhs);
  71.     return ret;
  72. }
  73.  
  74. // multiplication (point, constant)
  75. template<typename T>
  76. Point<T> operator*( const Point<T>& lhs, const T&  rhs) {
  77.     Point<T> ret( lhs.x * rhs, lhs.y * rhs);
  78.     return ret;
  79. }
  80.  
  81. // multiplicaton (constant, point)
  82. template<typename T>
  83. Point<T> operator*( const T&  lhs, const Point<T>& rhs) {
  84.     return rhs * lhs;
  85. }
  86.  
  87. // print out a co-ordinate in (x, y) form
  88. template<typename T>
  89. ostream& operator<<( ostream& os, const Point<T>& rhs) {
  90.     os << "(" << rhs.x << ", " << rhs.y << ")" ;
  91.     return os;
  92. }
  93.  
  94. // data structure with point
  95. typedef Point <double> PointD;
  96. typedef Point <int> PointI;
  97. typedef pair <PointD, PointD> SegmentD;
  98. typedef vector <PointD> vp;
  99.  
  100. // Cross product (x1*y2 - x2*y1)
  101. template<typename T>
  102. T cross( const Point<T>& A, const Point<T>& B ) {
  103.     return A.x*B.y - A.y*B.x;
  104. }
  105.  
  106. const double tolerance = 0.000002;
  107.  
  108.  
  109.  
  110.  
  111. /*
  112. vector p1p2 ; p1p3
  113. returns
  114. -1 if p1p3 is clockwise of p1p2 ( "right turn" )
  115. +1 if p1p3 is counter-clockwise of p1p2 ( "left turn " )
  116. 0 if parallel (overlapped)
  117. */
  118. template<typename T>
  119. int  ccw(  const Point<T>& p1,
  120.            const Point<T>& p2, const Point<T>& p3) {
  121.     Point<T> v1 = p2 - p1;
  122.     Point<T> v2 = p3 - p1;
  123.  
  124.     T cp = cross(v1, v2);
  125.  
  126.     //v2 is counter clockwise to v1, so we turned left
  127.     if (cp > 0)
  128.         return +1;
  129.  
  130.     //v2 is clockwise of v1,
  131.     if (cp < 0)
  132.         return -1;
  133.  
  134.     //Vectors v1 and v2 are colinear
  135.     return 0;
  136. }
  137.  
  138. // almost same as above
  139. template<>
  140. int ccw<double>(  const Point<double>& p1,
  141.                   const Point<double>& p2, const Point<double>& p3) {
  142.     Point<double> v1 = p2 - p1;
  143.     Point<double> v2 = p3 - p1;
  144.  
  145.     double cp = cross(v1, v2);
  146.  
  147.     //Vectors v1 and v2 are colinear
  148.     if (abs(cp) < tolerance) {
  149.         return 0;
  150.     }
  151.  
  152.     //v2 is counter clockwise to v1, so we turned left
  153.     if (cp > 0)
  154.         return +1;
  155.  
  156.     //v2 is clockwise of v1,
  157.     if (cp < 0)
  158.         return -1;
  159.  
  160.     // scape from above conditions, so some shit happens
  161.     int up = 3;
  162.     throw up;
  163. }
  164.  
  165. // দুইটি বিন্দুর দূরত্ব
  166. double dist( const PointD& p1, const PointD& p2 ) {
  167.     return sqrt( (p1.x-p2.x) * (p1.x-p2.x) + (p1.y-p2.y) * (p1.y-p2.y) );
  168. }
  169.  
  170. // স্থানাঙ্ক তুলনা (point i point j এর থেকে বড়, ছোট বা সমান কিনা)
  171. bool cmp(const PointI& i, const PointI& j) {
  172.     return (i.x != j.x)  ?
  173.            i.x < j.x :
  174.            i.y < j.y;
  175. }
  176.  
  177. // স্থানাঙ্ক তুলনা (point b point a এর থেকে বড়, ছোট বা সমান কিনা)
  178. int cmpYX(const PointI& a, const PointI& b) {
  179.     if (a.y != b.y) {
  180.         return a.y < b.y;
  181.     }
  182.     return a.x < b.x;
  183. }
  184.  
  185. /** সরলরেখা **/
  186.  
  187. template<typename T> T gcd(T a, T b) {
  188.     if (a == 0)
  189.         return b;
  190.     while (b != 0) {
  191.         if (a > b)
  192.             a = a - b;
  193.         else
  194.             b = b - a;
  195.     }
  196.     return a;
  197. }
  198.  
  199. template<class T>
  200. class Line {
  201. public:
  202.     //ax + by + c = 0
  203.     T A, B, C;
  204.  
  205.     //  সরলরেখার উপর অবস্থিত দুইটি বিন্দুর স্থানাঙ্ক দেয়া থাকলে রেখার সমীকরণ in ax + by + c = 0 form
  206.     // i.e. (4, 2) & (6, 4) দিয়ে যায় এমন রেখার সমীকরণ x - y - 2 = 0
  207.     Line(const Point<T>& p1, const Point<T>& p2) {
  208.  
  209.         // Building line
  210.         A = p1.y - p2.y;
  211.         B = p2.x - p1.x;
  212.         C = p1.x*p2.y - p2.x * p1.y;
  213.  
  214.         //make A positive
  215.         if (A < 0 || (A==0 && B < 0) ) {
  216.             A *= -1;
  217.             B *= -1;
  218.             C *= -1;
  219.         }
  220.  
  221.         int gcdAB = gcd( abs(A), abs(B) );
  222.         int gcdABC = gcd( gcdAB, abs(C) );
  223.  
  224.         A /= gcdABC;
  225.         B /= gcdABC;
  226.         C /= gcdABC;
  227.  
  228.         assert(A * p1.x + B * p1.y + C == 0);
  229.         assert(A * p2.x + B * p2.y + C == 0);
  230.     }
  231. };
  232.  
  233. // সরলরেখা lhs(Ax + By + C = 0) এবং rhs(Ax + By + C = 0) এর জন্য অপারেটর ওভারলোডিং :
  234.  
  235. // less than equal to
  236. template<typename T>
  237. bool operator<( const Line<T>& lhs, const Line<T>& rhs) {
  238.     if (lhs.A != rhs.A)
  239.         return lhs.A < rhs.A;
  240.  
  241.     if (lhs.B != rhs.B)
  242.         return lhs.B < rhs.B;
  243.  
  244.     return lhs.C < rhs.C;
  245. }
  246.  
  247. // দুইটি সরলরেখার উপর অবস্থিত দুইটি করে বিন্দু (x1, y1), (x2, y2) দেয়া আছে । দেখতে হবে সমান্তরাল কিনা
  248. // A - p1(x1, y1), p2(x2, y2)
  249. // B - p3(x3, y3), p4(x4, y4)
  250. // x = calculate cross product of (p2 - p1), (p4 - p3)
  251. // if x < ~0 then parallel
  252. bool isParallel( const SegmentD& seg1, const SegmentD& seg2) {
  253.     double z = cross(seg1.second - seg1.first, seg2.second - seg2.first );
  254.  
  255.     if (abs(z) < tolerance)
  256.         return true;
  257.  
  258.     return false;
  259. }
  260.  
  261. // দুইটি বিন্দু দেয়া থাকলে ওই বিন্দুদ্বয় দ্বারা গঠিত সরলরেখার কোন পাশে তৃতীয় বিন্দুটি অবস্থিত সেটা বের করে
  262. // i.e. (2, 2) is in upside(1) and (2, -2) is in downside(-1) of Line formed with (0, 0) and (4, 0)
  263. // i.e. again (2, 2) is in rightside(1) and (-2, 2) is in leftside(-1) of Line formed with (0, 0) and (0, 4)
  264. // তিনটি বিন্দুই একই সরলরেখায় অবস্থিত হলে ০ রিটার্ন করে।
  265. template<typename T>
  266. int getSide( const Point<T>& A, const Point<T>& B, const Point<T>& P) {
  267.     T z = cross(B - A, P - A);
  268.  
  269.     if (numeric_limits<T>::is_exact) {
  270.         if (z > 0) {
  271. #ifndef DEBUG
  272.             cout << "Points " << A << " " << B << " " << P << " 1 " << endl;
  273. #endif
  274.             return 1;
  275.         }
  276.         if (z < 0) {
  277. #ifndef DEBUG
  278.             cout << "Points " << A << " " << B << " " << P << " -1 " << endl;
  279. #endif
  280.             return -1;
  281.         }
  282.     } else {
  283.         if (z > tolerance)
  284.             return 1;
  285.         if (z < tolerance)
  286.             return -1;
  287.     }
  288.  
  289. #ifndef DEBUG
  290.     cout << "Points " << A << " " << B << " " << P << " 0 " << endl;
  291. #endif
  292.     return 0;
  293. }
  294.  
  295. // তিনটি বিন্দু সরলরৈখিক কিনা
  296. template<typename T>
  297. bool isColinear(  const Point<T>& p1,
  298.                   const Point<T>& p2, const Point<T>& p3) {
  299.     return 0 == getSide(p1, p2, p3);
  300. }
  301.  
  302. // এক্স a ও b এর মধ্যে কিনা
  303. template<typename T>
  304. bool isBetween(T x, T a, T b) {
  305.     return (a <= x && x <= b) ||
  306.            (b <= x && x <= a);
  307. }
  308.  
  309. // (a1, a2) দ্বারা ও (b1, b2) দ্বারা গঠিত সরলরেখা পরস্পরকে ছেদ করে কিনা
  310. template<typename T>
  311. bool intersects(const Point<T>& a1, const Point<T>& a2,
  312.                 const Point<T>& b1, const Point<T>& b2) {
  313.     if (a1==a2) {
  314.         return isBetween(a1.x, b1.x, b2.x) &&
  315.                isBetween(a1.y, b1.y, b2.y);
  316.     }
  317.  
  318.     if ( getSide( a1, a2, b1 ) == getSide( a1, a2, b2 ) )
  319.         return false;
  320.  
  321.  
  322.     if (b1==b2) {
  323.         return isBetween(b1.x, a1.x, a2.x) &&
  324.                isBetween(b1.y, a1.y, a2.y);
  325.     }
  326.  
  327.     if ( getSide( b1, b2, a1) == getSide( b1, b2, a2 ) )
  328.         return false;
  329.  
  330.     return true;
  331. }
  332.  
  333. //http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
  334. // দুইটি সরলরেখা (x, y) বিন্দুতে ছেদ করবে কিনা
  335. bool getIntersection( const SegmentD& seg1, const SegmentD& seg2, PointD& inter) {
  336.     PointD p = seg1.first;
  337.     PointD r = seg1.second - seg1.first;
  338.  
  339.     PointD q = seg2.first;
  340.     PointD s = seg2.second - seg2.first;
  341.  
  342.     //P + t*r intersects q + u*s
  343.  
  344.     double rCrossS = cross(r, s);
  345.  
  346.     if ( abs( rCrossS ) < tolerance )
  347.         return false;
  348.  
  349.     double t = cross(q-p, s / rCrossS);
  350.  
  351.     if (t + tolerance < 0 || t-tolerance > 1)
  352.         return false;
  353.     // double u = cross(q-p, r / rCrossS);
  354.  
  355.     inter = p + t*r;
  356.     return true;
  357. }
  358.  
  359. typedef vector<PointI> vecP ;
  360.  
  361. // দুইটি সরলরেখা সমান কিনা
  362. bool cmpLine(const vecP& v1, const vecP& v2) {
  363.     int i = 0;
  364.     while( i < v1.size() && i < v2.size() ) {
  365.         if (v1[i] != v2[i]) {
  366.             return cmp(v1[i], v2[i]);
  367.         }
  368.         ++i;
  369.     }
  370.  
  371.     return v1.size() < v2.size();
  372. }
  373.  
  374. // Not completed yet
  375. template<typename T>
  376. struct PolarCmp {
  377.     Point<T> origin;
  378.  
  379.     PolarCmp( const Point<T> ori ) : origin(ori) {}
  380.  
  381.     int operator()(const Point<T>& a, const Point<T>& b) {
  382.         int isCCW = ccw(origin, a, b);
  383.  
  384.         if (isCCW == 1)
  385.             return true;
  386.  
  387.         return false;
  388.     }
  389. };
  390.  
  391.  
  392. int main() {
  393. #ifndef ONLINE_JUDGE
  394.     freopen ("input.txt","r",stdin);
  395. #endif
  396.     Line <int> l = Line <int> (PointI(4, 2), PointI(6, 4));
  397.     pf("%d %d %d\n", l.A, l.B, l.C);
  398.     pf("%d\n", getSide(PointI(0, 0), PointI(4, 0), PointI(2, 2)));
  399.     pf("%d\n", getSide(PointI(0, 0), PointI(4, 0), PointI(2, -2)));
  400.     pf("%d\n", getSide(PointI(0, 0), PointI(4, 0), PointI(8, 0)));
  401.     return 0;
  402. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement