Advertisement
blufzzz

Fivt_3/task-B/23.11.2017

Nov 22nd, 2017
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.97 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <iostream>
  4. #include <vector>
  5. #include <cassert>
  6.  
  7.  
  8. struct Point {
  9.     int  x;
  10.     int  y;
  11.     int  z;
  12.     int number;
  13.     Point(int _x, int _y, int _z, int _number = 0):
  14.             x(_x),
  15.             y(_y),
  16.             z(_z),
  17.             number(_number)
  18.     {
  19.     }
  20.     bool operator==(const Point& other) const;
  21.     bool operator!=(const Point& other) const;
  22.     Point operator-(const Point& other) const;
  23.     double operator^(int p) const;
  24.     double operator*(const Point& other) const;
  25.     Point OtherPointFromSet(const std::vector<Point>& points);
  26. };
  27.  
  28.  
  29. bool Point::operator==(const Point &other) const{
  30.     return (this->x == other.x && this->y == other.y && this->z == other.z);
  31. }
  32.  
  33.  
  34. bool Point::operator!=(const Point &other) const{
  35.     return (this->x != other.x || this->y != other.y || this->z != other.z);
  36. }
  37.  
  38. Point Point::operator-(const Point& other) const{
  39.     return {this->x - other.x, this->y - other.y, this->z - other.z};
  40. }
  41.  
  42.  
  43. double Point::operator^(int p) const{
  44.     return std::pow(this->x,p) + std::pow(this->y,p) + std::pow(this->z,p);
  45. }
  46.  
  47.  
  48. double Point::operator*(const Point &other) const{
  49.     return (this->x*other.x + this->y*other.y + this->z*other.z);
  50. }
  51.  
  52. Point Point::OtherPointFromSet(const std::vector<Point> &points) {
  53.     assert(points.size() != 0);
  54.     for(auto point: points ) {
  55.         if (point != *this) {
  56.             return point;
  57.         }
  58.     }
  59. }
  60.  
  61.  
  62. Point VectorMultiplication(const Point& p1, const Point& p2) {
  63.     return {p1.y*p2.z - p1.z*p2.y, - (p1.x*p2.z - p1.z*p2.x ), p1.x*p2.y - p1.y*p2.x};
  64. }
  65.  
  66. double Distance(const Point& p1, const Point& p2) {
  67.     return std::sqrt( (p1-p2)^2 );
  68. }
  69.  
  70.  
  71. double OzAngle(const Point& p1, const Point& p2) {
  72.     Point Oz (0,0,1);
  73.     Point p12  = p2 - p1;
  74.     double t = (p12*Oz)/std::sqrt((p12*p12)*(Oz*Oz));
  75.     if (t < -1) {
  76.         t = -1;
  77.     }
  78.     else if(t > 1) {
  79.         t = 1;
  80.     }
  81.     double acos = std::acos(t);
  82.     return acos;
  83. }
  84.  
  85. // ??
  86. // дост ли самой нижней??
  87. Point MostBottom(std::vector<Point> &points) {
  88.     Point point_min = points[0];
  89.     for (auto point: points) {
  90.         if (point.z < point_min.z) {
  91.             point_min = point;
  92.         }
  93.     }
  94.     return point_min;
  95. }
  96.  
  97. template <class Triangle>
  98. struct Edge {
  99.     Point p1;
  100.     Point p2;
  101.     bool IsProcessed;
  102.     Triangle* triangle;
  103.     Edge(Point _p1, Point _p2, Triangle* _triangle);
  104.     Point PivotAroundEdge(std::vector<Point>& points, const Point& forbidden_point);
  105.     Point PivotAroundEdge(std::vector<Point> &points);
  106.     Point GetForbiddenPoint() const;
  107.     bool operator==(const Edge& other);
  108. };
  109.  
  110.  
  111. template <class Triangle>
  112. Edge<Triangle>::Edge(Point _p1, Point _p2, Triangle* _triangle) :
  113.         p1(_p1),
  114.         p2(_p2),
  115.         IsProcessed(false),
  116.         triangle(_triangle)
  117. {
  118. }
  119.  
  120.  
  121. template <class Triangle>
  122. bool Edge<Triangle>::operator==(const Edge<Triangle> &other) {
  123.     return (this->p1 == other.p1 && this->p2 == other.p2);
  124. }
  125.  
  126.  
  127. template <class Triangle>
  128. Point Edge<Triangle>::GetForbiddenPoint() const {
  129.     for (auto point: triangle->GetPoints()) {
  130.         if (point != p1 && point != p2) {
  131.             return  point;
  132.         }
  133.     }
  134.     throw "GetForbiddenPoint ERROR";
  135. }
  136.  
  137.  
  138. struct Triangle {
  139.     Edge<Triangle> edge12;
  140.     Edge<Triangle> edge23;
  141.     Edge<Triangle> edge31;
  142.     std::vector<Edge<Triangle>>GetEdges() const;
  143.     std::vector<Point> GetPoints() const;
  144.     Triangle(const Edge<Triangle>& edge1, const Point& point);
  145.     Triangle(const Edge<Triangle>& edge1, const Edge<Triangle>& edge2, const Edge<Triangle>& edge3);
  146. //  std::vector<Point> ProperOrder();
  147. };
  148.  
  149. Triangle::Triangle(const Edge<Triangle> &edge, const Point &point) :
  150.     edge12(edge),
  151.     edge23(Edge<Triangle>(edge.p1, point, this)), //??
  152.     edge31(Edge<Triangle>(edge.p2, point, this)) //??
  153. {
  154. }
  155.  
  156.  
  157. Triangle::Triangle(const Edge<Triangle> &edge1, const Edge<Triangle> &edge2, const Edge<Triangle> &edge3) :
  158.     edge12(edge1),
  159.     edge23(edge2),
  160.     edge31 (edge3)
  161. {
  162. }
  163.  
  164. std::vector<Point> Triangle::GetPoints() const{
  165.     std::vector<Point> points = {edge12.p1, edge12.p2, edge23.p1, edge23.p2, edge31.p1, edge31.p2 };
  166.     for (int i = 0; i < points.size(); ++i) {
  167.         for (int j = 0; j < points.size(); ++j) {
  168.             if (points[i] == points[j] && i != j) {
  169.                 points.erase(points.begin() + j);
  170.                 break;
  171.             }
  172.         }
  173.     }
  174.     return points;
  175. }
  176.  
  177. std::vector<Edge<Triangle>> Triangle::GetEdges() const{
  178.     std::vector<Edge<Triangle>> edges = {edge12,edge23,edge31};
  179.     return edges;
  180. }
  181.  
  182.  
  183. double FindOutFaceD(double A, double B, double C, const Point& pivot) {
  184.     return -( A*pivot.x + B*pivot.y + C*pivot.z );
  185. }
  186.  
  187. bool IsFace(const Triangle& triangle, const std::vector<Point>& points) { // O(n)
  188.     const std::vector<Point> triangles_points = triangle.GetPoints();
  189.     Point v1 = triangles_points[1] - triangles_points[0];
  190.     Point v2 = triangles_points[2] - triangles_points[0];
  191.     Point normal (VectorMultiplication(v1,v2));
  192.     double D_of_triangle = FindOutFaceD(normal.x, normal.y, normal.z, triangles_points[0]);
  193.     std::vector<double> D_of_other_points;
  194.     for (auto point: points) {
  195.         if ( (point !=  triangles_points[1] && point !=  triangles_points[2]) && point !=  triangles_points[0]) {
  196.             double D = FindOutFaceD(normal.x, normal.y, normal.z, point);
  197.             D_of_other_points.push_back(D);
  198.         }
  199.     }
  200.     double min_element = *std::min_element(D_of_other_points.begin(), D_of_other_points.end());
  201.     double max_element = *std::max_element(D_of_other_points.begin(), D_of_other_points.end());
  202.     bool result = (D_of_triangle < min_element ||
  203.             D_of_triangle > max_element ) ;
  204.     return result;
  205. }
  206.  
  207.  
  208.  
  209. Edge<Triangle> FindEdgeOnHull(std::vector<Point>& points) {
  210.     Point p1 = MostBottom(points);
  211.     Point p2 = p1.OtherPointFromSet(points);
  212.     for (auto point: points) {
  213.         if ( p1 != point && OzAngle(p1,point) >= OzAngle(p1,p2) ) {
  214.             p2 = point;
  215.         }
  216.     }
  217.     return {p1,p2, nullptr};
  218. }
  219.  
  220. Triangle FindtTriangleOnHull(std::vector<Point>& points) {
  221.     Edge<Triangle> edge = FindEdgeOnHull(points);
  222.     Point pivot = edge.PivotAroundEdge(points);
  223.     return Triangle(edge, pivot); //тут можно не запоминать
  224. }
  225.  
  226.  
  227.  
  228. // вернет такую точку, что получилась грань
  229. template <class Triangle>
  230. Point Edge<Triangle>::PivotAroundEdge(std::vector<Point> &points, const Point& forbidden_point) { // O(n^2)
  231.     assert(points.size() > 2); // не должно быть совпад
  232.     Point p1 = this->p1;
  233.     Point p2 = this->p2;
  234.     double current_angle = 0;
  235.     for (auto point: points) {
  236.         if ((point != p1 && point != p2) && point != forbidden_point) {
  237.             Edge<Triangle> this_edge = *this;
  238.             Triangle triangle (this_edge, point);
  239.             if (IsFace(triangle, points)) { // O(n)
  240.                 this->IsProcessed = true; //??
  241.                 return point;
  242.             }
  243.         }
  244.     }
  245. }
  246.  
  247. template <class Triangle>
  248. Point Edge<Triangle>::PivotAroundEdge(std::vector<Point> &points) { // O(n^2)
  249.     assert(points.size() > 2); // не должно быть совпад
  250.     Point p1 = this->p1;
  251.     Point p2 = this->p2;
  252.     double current_angle = 0;
  253.     for (auto point: points) {
  254.         if ((point != p1 && point != p2)) {
  255.             Edge<Triangle> this_edge = *this;
  256.             Triangle triangle (this_edge, point);
  257.             if (IsFace(triangle, points)) { // O(n)
  258.                 return point;
  259.             }
  260.         }
  261.     }
  262. }
  263.  
  264.  
  265. bool IsNotUsedEdges(std::vector<Edge<Triangle>> edges) {
  266.     bool result = true;
  267.     for (auto edge: edges) {
  268.         result = result && edge.IsProcessed;
  269.     }
  270.     return  !result;
  271. }
  272.  
  273. template <class T>
  274. bool IsIn(T myelement, std::vector<T>& elements) {
  275.     for (auto element: elements) {
  276.         if (myelement == element) {
  277.             return true;
  278.         }
  279.     }
  280.     return  false;
  281. }
  282.  
  283.  
  284. void GiftWrapping(std::vector<Point>& points, std::vector<Triangle>& faces) {
  285.     Triangle t = FindtTriangleOnHull(points);
  286.     faces.push_back(t);
  287.     std::vector<Edge<Triangle>> edges = t.GetEdges(); // начальная хуйня
  288.     while (IsNotUsedEdges(edges)) { // O(n)
  289.         Edge<Triangle>& newedge = edges.back();
  290. //      edges.pop_back();
  291.         if (!newedge.IsProcessed) {
  292.             Point pivot = newedge.PivotAroundEdge(points, newedge.GetForbiddenPoint());
  293.             Triangle newtriangle (newedge, pivot); //O(n)
  294.             for (auto triangles_edge: newtriangle.GetEdges()) {
  295.                 if (!IsIn(triangles_edge, edges)) { // таких еще нету
  296.                     edges.push_back(triangles_edge);
  297.                 }
  298.             }
  299.             faces.push_back(newtriangle); // IsIn??
  300.             std::cout<<faces.size()<<std::endl;
  301.         }
  302.     }
  303. }
  304.  
  305. int main() {
  306.  
  307.     Point p1 (1,0,0);
  308.     Point p2 (0,1,0);
  309.     Point p3 (0,0,1);
  310.     Point p4 (0,0,0);
  311. //  Point p5 (1,0,-1);
  312.  
  313.     std::vector<Point> points = {p1,p2,p3,p4};
  314.     std::vector<Triangle> faces;
  315.  
  316.     GiftWrapping(points, faces);
  317.  
  318.  
  319. //  std::cout<<OzAngle(p1,p2);
  320. //  std::cout<<' ';
  321. //  std::cout<<OzAngle(p1,p5);
  322.  
  323.  
  324.  
  325.     return  0;
  326. }
  327.  
  328.  
  329.  
  330. //  int m; // число тестов
  331. //  std::cin>>m;
  332. //
  333. //  for (int i = 0; i < m; ++i) {
  334. //      int n; // число точек
  335. //      std::cin>>n;
  336. //      std::vector<Point> points;
  337. //      std::vector<Triangle> faces;
  338. //      for (int j = 0; j < n; ++j) {
  339. //          int x,y,z;
  340. //          std::cin>>x>>y>>z;
  341. //          points.emplace_back(Point(x,y,z,j));
  342. //      }
  343. //      GiftWrapping(points, faces);
  344. //      std::cout<<faces.size()<<std::endl;
  345. //      for (auto face: faces) {
  346. //          std::cout<<3<<' ';
  347. //          for (auto point: face.ProperOrder()) {
  348. //              std::cout<<point.number<<' ';
  349. //          }
  350. //          std::cout<<'\n';
  351. //      }
  352. //  }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement