Advertisement
faunuss

Stable

Nov 27th, 2017
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.91 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <queue>
  5. #include <set>
  6. #include <algorithm>
  7. using namespace std;
  8.  
  9. class ConvexHull {
  10. public:
  11.     explicit ConvexHull(size_t num) {
  12.         dots.clear();
  13.         num_dots = num;
  14.     }
  15.     ~ConvexHull() {
  16.         dots.clear();
  17.     }
  18.     void read_dots(){
  19.         for(int i = 0; i < num_dots; i++) {
  20.             double x = 0;
  21.             double y = 0;
  22.             double z = 0;
  23.             cin >> x >> y >> z;
  24.             Point tmp(x, y, z);
  25.             tmp.num = i;
  26.             dots.push_back(tmp);
  27.         }
  28.     }
  29.     void print_convex() {
  30.         set<Flat>ans;
  31.  
  32.         Point First = dots[0];
  33.         Point Second = dots[1];
  34.         Point Third = dots[2];
  35.  
  36.         Initilize(First,Second, Third);
  37.  
  38.         queue<Flat> faces;
  39.  
  40.  
  41.         Point vp = CrossProduct(Point(First, Second), Point(First, Third));
  42.         Point n = CrossProduct(Point(First, Second), Point(First, Third));
  43.         int someDot;
  44.         for (int i = 0; i < 4; ++i) {
  45.             if (First.num == i) {continue;}
  46.             if (Second.num == i) {continue;}
  47.             if (Third.num == i) {continue;}
  48.             someDot = i;
  49.             break;
  50.         }
  51.         if (Scalar(n, Point(First, dots[someDot])) > 0) {
  52.             n.x = - n.x;
  53.             n.y = - n.y;
  54.             n.z = - n.z;
  55.         }
  56.  
  57.         if (vp.x * n.x <= 0 && vp.y * n.y <= 0 && vp.z * n.z <= 0) {
  58.             Point tmp = Second;
  59.             Second = Third;
  60.             Third = tmp;
  61.         }
  62.  
  63.         Flat FirstFace = Flat(First, Second, Third,dots);
  64.  
  65.         faces.push(FirstFace);
  66.         ans.insert(FirstFace);
  67.  
  68.         while(!faces.empty()) {
  69.             Flat face = faces.front();
  70.             Point n = face.Normal(dots);
  71.             double g1 = -2, g2 = -2, g3 = -2;
  72.             Flat f1, f2, f3;
  73.             for (int i = 0 ; i < dots.size(); ++i) {
  74.                 if (face.First.num != i && face.Second.num != i && face.Third.num != i) {
  75.                     Flat f1_test = Flat(face.First, dots[i], face.Second, dots);
  76.                     Flat f2_test = Flat(face.Second, dots[i], face.Third, dots);
  77.                     Flat f3_test = Flat(face.Third, dots[i], face.First, dots);
  78.                     Point n1 = CrossProduct(Point(f1_test.First,f1_test.Second),Point(f1_test.First,f1_test.Third));
  79.                     Point n2 = CrossProduct(Point(f2_test.First,f2_test.Second),Point(f2_test.First,f2_test.Third));
  80.                     Point n3 = CrossProduct(Point(f3_test.First,f3_test.Second),Point(f3_test.First,f3_test.Third));
  81.                     double new_g1 = Scalar(n, n1) / n.Mod() / n1.Mod();
  82.                     double new_g2 = Scalar(n, n2) / n.Mod() / n2.Mod();
  83.                     double new_g3 = Scalar(n, n3) / n.Mod() / n3.Mod();
  84.                     if (new_g1 > g1) {
  85.                         g1 = new_g1;
  86.                         f1 = f1_test;
  87.                     }
  88.                     if (new_g2 > g2) {
  89.                         g2 = new_g2;
  90.                         f2 = f2_test;
  91.                     }
  92.                     if (new_g3 > g3) {
  93.                         g3 = new_g3;
  94.                         f3 = f3_test;
  95.                     }
  96.                 }
  97.             }
  98.             bool b1 = true, b2 = true, b3 = true;
  99.             if (ans.count(f1) != 0){b1 = false;}
  100.             if (ans.count(f2) != 0){b2 = false;}
  101.             if (ans.count(f3) != 0){b3 = false;}
  102.             if (f1 == f2) {b1 = false;}
  103.             if (f1 == f3) {b2 = false;}
  104.             if (f2 == f3) {b3 = false;}
  105.             if (b1) {
  106.                 faces.push(f1);
  107.                 ans.insert(f1);
  108.             }
  109.             if (b2) {
  110.                 faces.push(f2);
  111.                 ans.insert(f2);
  112.             }
  113.             if (b3) {
  114.                 faces.push(f3);
  115.                 ans.insert(f3);
  116.             }
  117.             faces.pop();
  118.         }
  119.         cout << ans.size() << endl;
  120.         for (Flat face: ans) {
  121.             cout << 3 << ' ' << face.First.num << ' ' << face.Second.num << ' ' << face.Third.num << endl;
  122.         }
  123.     }
  124. private:
  125.     const int MAX_COORDINATE = 1000000;
  126.     struct Point{
  127.         double x;   // Координата точки по x
  128.         double y;   // Координата точки по y
  129.         double z;   // Координата точки по z
  130.         int num;    // Номер точки
  131.  
  132.         double Mod(){
  133.             return sqrt(x*x+y*y+z*z);
  134.         }
  135.         Point() : x(0), y(0), z(0) {}
  136.         Point(Point A, Point B) : x(B.x-A.x), y(B.y-A.y), z(B.z-A.z), num(-1) {}
  137.         Point(double X, double Y, double Z) : x(X), y(Y), z(Z), num(-1) {}
  138.     };
  139.     Point static CrossProduct (const Point& A,const Point& B) {
  140.         return Point{
  141.                 .x = A.y*B.z-A.z*B.y,
  142.                 .y = A.z*B.x-A.x*B.z,
  143.                 .z = A.x*B.y-A.y*B.x,
  144.                 };
  145.     }
  146.     double static Scalar(const Point& A,const Point& B) {
  147.         return(A.x*B.x+A.y*B.y+A.z*B.z);
  148.     }
  149.  
  150.     double FindAngleBetweenPlanes(Point F1, Point F2,Point F3, Point S1, Point S2,Point S3)
  151.     {
  152.         Point normalF = CrossProduct(Point(F1, F2), Point(F1, F3)); //������� � ��������� F.
  153.         Point normalS = CrossProduct(Point(S1, S2), Point(S1, S3)); //������� � ��������� S.
  154.         return Scalar(normalF, normalS) / normalF.Mod() / normalS.Mod();
  155.     }
  156.  
  157.     vector<Point> dots;
  158.     size_t num_dots;
  159.  
  160.     struct Flat {
  161.         Point First;
  162.         Point Second;
  163.         Point Third;
  164.         Flat() : First(), Second(), Third() {}
  165.         Flat(Point F, Point S, Point T, vector<Point> dots) : First(F), Second(S), Third(T) {
  166.             while (Second.num < First.num || Third.num < First.num) {
  167.                 Point tmp = First;
  168.                 First = Second;
  169.                 Second = Third;
  170.                 Third = tmp;
  171.             }
  172.         }
  173.         Point Normal(vector<Point> dots) {
  174.             Point n = CrossProduct(Point(First, Second), Point(First, Third));
  175.             int someDot;
  176.             for (int i = 0; i < 4; ++i) {
  177.                 if (First.num == i) {continue;}
  178.                 if (Second.num == i) {continue;}
  179.                 if (Third.num == i) {continue;}
  180.                 someDot = i;
  181.                 break;
  182.             }
  183.             if (Scalar(n, Point(First, dots[someDot])) > 0) {
  184.                 n.x = - n.x;
  185.                 n.y = - n.y;
  186.                 n.z = - n.z;
  187.             }
  188.             return n;
  189.         }
  190.  
  191.         bool operator<(const Flat& other) const
  192.         {
  193.             return (First.num < other.First.num || (First.num == other.First.num && (Second.num < other.Second.num ||
  194.                                                      Second.num == other.Second.num && Third.num < other.Third.num))) ? true : false;
  195.         }
  196.  
  197.         bool operator==(const Flat& other) const
  198.         {
  199.             return (First.num == other.First.num & Second.num == other.Second.num && Third.num == other.Third.num) ? true : false;
  200.         }
  201.     };
  202.  
  203.     void Initilize(Point& First, Point& Second, Point& Third) {
  204.         for (int i = 0; i < num_dots; i++) {  // Находим эту самую точку first_point
  205.             if (dots[i].z < First.z) {
  206.                 First = dots[i];
  207.             } else if (dots[i].z == First.z) {
  208.                 if (dots[i].x < First.x) {
  209.                     First = dots[i];
  210.                 } else if (dots[i].x == First.x) {
  211.                     if (dots[i].y < First.y) {
  212.                         First = dots[i];
  213.                     }
  214.                 }
  215.             }
  216.         }
  217.  
  218.         double maxAngle = -1;
  219.         Point someDot = dots[First.num];
  220.         Point someAnotherDot = dots[First.num];
  221.         someDot.x -= 1;
  222.         someAnotherDot.y -= 1;
  223.         for (int i = 0; i < dots.size(); ++i) {
  224.             if (i != First.num) {
  225.                 double angle = FindAngleBetweenPlanes(dots[First.num], someDot, someAnotherDot,  dots[First.num], someDot, dots[i]);
  226.                     if (angle >= maxAngle) {
  227.                         maxAngle = angle;
  228.                         Second = dots[i];
  229.                     }
  230.                 }
  231.             }
  232.  
  233.         maxAngle = -2;
  234.         for (int i = 0; i < dots.size(); ++i) {
  235.             if (i != First.num && i != Second.num) {
  236.                 double angle = FindAngleBetweenPlanes(dots[First.num], someDot, Second,
  237.                                                       dots[First.num], Second, dots[i]);
  238.                 if (angle >= maxAngle) {
  239.                     maxAngle = angle;
  240.                     Third = dots[i];
  241.                 }
  242.             }
  243.         }
  244.     }
  245. };
  246.  
  247. int main() {
  248.     int num_tests = 0;
  249.     cin >> num_tests;
  250.  
  251.     for(int test = 0; test < num_tests; test++){
  252.         size_t num_dots = 0;
  253.         cin >> num_dots;
  254.  
  255.         ConvexHull shell(num_dots);
  256.         shell.read_dots();
  257.         shell.print_convex();
  258.     }
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement