Advertisement
blufzzz

Fivt_3/task-B/24.11.2017

Nov 23rd, 2017
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.59 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. Point MostBottom(std::vector<Point> &points) {
  87.     Point point_min = points[0];
  88.     for (auto point: points) {
  89.         if (point.z < point_min.z) {
  90.             point_min = point;
  91.         }
  92.     }
  93.     return point_min;
  94. }
  95.  
  96. template <class Triangle>
  97. struct Edge {
  98.     Point p1;
  99.     Point p2;
  100.     bool IsProcessed;
  101.     Triangle* parent_triangle;
  102.     Edge(Point _p1, Point _p2, Triangle* _triangle);
  103.     Point PivotAroundEdge(std::vector<Point>& points, const Point& forbidden_point);
  104.     Point PivotAroundEdge(std::vector<Point> &points);
  105.     Point GetForbiddenPoint() const;
  106.     bool operator==(const Edge& other) const;
  107. };
  108.  
  109.  
  110. template <class Triangle>
  111. Edge<Triangle>::Edge(Point _p1, Point _p2, Triangle* _triangle) :
  112.         p1(_p1),
  113.         p2(_p2),
  114.         IsProcessed(false),
  115.         parent_triangle(_triangle)
  116. {
  117. }
  118.  
  119.  
  120. template <class Triangle>
  121. bool Edge<Triangle>::operator==(const Edge<Triangle> &other) const{
  122.     return (this->p1 == other.p1 && this->p2 == other.p2 ||
  123.             this->p1 == other.p2 && this->p2 == other.p1);
  124. }
  125.  
  126.  
  127. template <class Triangle>
  128. Point Edge<Triangle>::GetForbiddenPoint() const {
  129.     for (auto point: parent_triangle->GetPoints()) {
  130.         if (point != p1 && point != p2) {
  131.             return  point;
  132.         }
  133.     }
  134.     std::cout<<"Not ForbiddenPoint for Edge";
  135.     exit(1);
  136. }
  137.  
  138.  
  139. double FindOutFaceD(double A, double B, double C, const Point& pivot) {
  140.     return -( A*pivot.x + B*pivot.y + C*pivot.z );
  141. }
  142.  
  143.  
  144. struct Triangle {
  145.     Edge<Triangle> edge12;
  146.     Edge<Triangle> edge23;
  147.     Edge<Triangle> edge31;
  148.     Point GetExternalVector(const std::vector<Point>& points) const;
  149.     Point GetOtherPoint(const std::vector<Point>& points) const;
  150.     std::vector<Edge<Triangle>>GetEdges() const;
  151.     std::vector<Point> GetPoints() const;
  152.     std::vector<Point> PointsInProperOrder(const std::vector<Point>& points) const;
  153.     Triangle(const Edge<Triangle>& edge, const Point& point);
  154.     Triangle(const Edge<Triangle>& edge1, const Edge<Triangle>& edge2, const Edge<Triangle>& edge3);
  155. };
  156.  
  157. Triangle::Triangle(const Edge<Triangle>& edge, const Point &point) :
  158.     edge12(edge),
  159.     edge23(Edge<Triangle>(edge.p1, point, this)),
  160.     edge31(Edge<Triangle>(edge.p2, point, this))
  161. {
  162. }
  163.  
  164.  
  165. Triangle::Triangle(const Edge<Triangle> &edge1, const Edge<Triangle> &edge2, const Edge<Triangle> &edge3) :
  166.     edge12(edge1),
  167.     edge23(edge2),
  168.     edge31(edge3)
  169. {
  170. }
  171.  
  172.  
  173. Point Triangle::GetExternalVector(const std::vector<Point>& points) const {
  174.     const std::vector<Point> triangles_points = this->GetPoints();
  175.     Point v1 = triangles_points[1] - triangles_points[0];
  176.     Point v2 = triangles_points[2] - triangles_points[0];
  177.     Point vector_normal_1 = VectorMultiplication(v1,v2);
  178.     Point vector_normal_2 = VectorMultiplication(v2,v1);
  179.     double D_1 = FindOutFaceD(vector_normal_1.x, vector_normal_1.y, vector_normal_1.z, triangles_points[0]);
  180.     double D_2 = FindOutFaceD(vector_normal_2.x, vector_normal_2.y, vector_normal_2.z, triangles_points[0]);
  181.     Point other_point = this->GetOtherPoint(points);
  182.     if (vector_normal_1*other_point + D_1 < 0) {
  183.         return vector_normal_1;
  184.     }
  185.     else if (vector_normal_2*other_point + D_2 < 0) {
  186.         return vector_normal_2;
  187.     }
  188.     else {
  189.         std::cout<<"Can't Find External Vector for Triangle";
  190.         exit(1);
  191.     }
  192. }
  193.  
  194.  
  195. std::vector<Point> Triangle::GetPoints() const{
  196.     std::vector<Point> points = {edge12.p1, edge12.p2, edge23.p1, edge23.p2, edge31.p1, edge31.p2 };
  197.     for (int i = 0; i < points.size(); ++i) {
  198.         for (int j = 0; j < points.size(); ++j) {
  199.             if (points[i] == points[j] && i != j) {
  200.                 points.erase(points.begin() + j);
  201.                 break;
  202.             }
  203.         }
  204.     }
  205.     return points;
  206. }
  207.  
  208.  
  209.  
  210. struct {
  211.     bool operator()(const Point& a, const Point& b) const
  212.     {
  213.         return a.number < b.number;
  214.     }
  215. } ComparePointByNumber;
  216. std::vector<Point> Triangle::PointsInProperOrder(const std::vector<Point>& points) const {
  217.     std::vector<Point> triangle_points = this->GetPoints();
  218.     std::vector<Point> proper_order_points;
  219.     Point external_normal_vector = this->GetExternalVector(points);
  220.     int iter_of_min = 0;                                                                            //FIX!!!
  221.     for (int i = 1; i < triangle_points.size(); ++i) {
  222.         if (triangle_points[iter_of_min].number > triangle_points[i].number) {
  223.             iter_of_min = i;
  224.         }
  225.     }
  226.     std::swap(triangle_points[iter_of_min],triangle_points[0]);
  227.     proper_order_points.push_back(triangle_points[0]);
  228.  
  229.     Point v1 = VectorMultiplication(triangle_points[1] - triangle_points[0],external_normal_vector);
  230.     Point v2 = VectorMultiplication(triangle_points[2] - triangle_points[0],external_normal_vector);
  231.     double D_1 = FindOutFaceD(v1.x , v1.y, v1.z, triangle_points[1]);
  232.     double D_2 = FindOutFaceD(v2.x , v2.y, v2.z, triangle_points[2]);
  233.     if ( v1*triangle_points[2] + D_1 < 0 ) {
  234.         proper_order_points.push_back(triangle_points[1]);
  235.         proper_order_points.push_back(triangle_points[2]);
  236.     }
  237.     else if ( v2*triangle_points[1] + D_2 < 0 ) {
  238.         proper_order_points.push_back(triangle_points[2]);
  239.         proper_order_points.push_back(triangle_points[1]);
  240.     }
  241.     else {
  242.         std::cout<<"Can't find right order";
  243.         exit(1);
  244.     }
  245.     return proper_order_points;
  246. }
  247.  
  248.  
  249. std::vector<Edge<Triangle>> Triangle::GetEdges() const{
  250.     std::vector<Edge<Triangle>> edges = {edge12,edge23,edge31};
  251.     return edges;
  252. }
  253.  
  254. Point Triangle::GetOtherPoint(const std::vector<Point> &points) const {
  255.     const std::vector<Point> triangles_points = this->GetPoints();
  256.     for (auto point: points) {
  257.         if ((point != triangles_points[1] && point != triangles_points[2])
  258.             && point != triangles_points[0]) {
  259.             return point;
  260.         }
  261.     }
  262.     std::cout<<"No other points for triangle";
  263.     exit(1);
  264. }
  265.  
  266.  
  267. bool IsFace(const Triangle& triangle, const std::vector<Point>& points) { // O(n)
  268.     const std::vector<Point> triangles_points = triangle.GetPoints();
  269.     Point normal = triangle.GetExternalVector(points);
  270.  
  271.     double D_of_triangle = FindOutFaceD(normal.x, normal.y, normal.z, triangles_points[0]);
  272.     std::vector<double> D_of_other_points;
  273.     for (auto point: points) {
  274.         if ( (point !=  triangles_points[1] && point !=  triangles_points[2]) && point !=  triangles_points[0]) {
  275.             double D = FindOutFaceD(normal.x, normal.y, normal.z, point);
  276.             D_of_other_points.push_back(D);
  277.         }
  278.     }
  279.     double min_element = *std::min_element(D_of_other_points.begin(), D_of_other_points.end());
  280.     double max_element = *std::max_element(D_of_other_points.begin(), D_of_other_points.end());
  281.     bool result = (D_of_triangle < min_element ||
  282.             D_of_triangle > max_element ) ;
  283.     return result;
  284. }
  285.  
  286.  
  287.  
  288. Edge<Triangle> FindEdgeOnHull(std::vector<Point>& points) {
  289.     Point p1 = MostBottom(points);
  290.     Point p2 = p1.OtherPointFromSet(points);
  291.     for (auto point: points) {
  292.         if ( p1 != point && OzAngle(p1,point) >= OzAngle(p1,p2) ) {
  293.             p2 = point;
  294.         }
  295.     }
  296.     return {p1,p2, nullptr};
  297. }
  298.  
  299. Triangle FindtTriangleOnHull(std::vector<Point>& points) {
  300.     Edge<Triangle> edge = FindEdgeOnHull(points);
  301.     Point pivot = edge.PivotAroundEdge(points);
  302.     Triangle triangle(edge, pivot);
  303.     triangle.edge12.parent_triangle = &triangle;
  304.     return  triangle;
  305. }
  306.  
  307.  
  308.  
  309. // вернет такую точку, что получилась грань
  310. template <class Triangle>
  311. Point Edge<Triangle>::PivotAroundEdge(std::vector<Point> &points, const Point& forbidden_point) { // O(n^2)
  312.     assert(points.size() > 2); // не должно быть совпад
  313.     Point p1 = this->p1;
  314.     Point p2 = this->p2;
  315.     double current_angle = 0;
  316.     for (auto point: points) {
  317.         if ((point != p1 && point != p2) && point != forbidden_point) {
  318.             Edge<Triangle> this_edge = *this;
  319.             Triangle triangle (this_edge, point);
  320.             if (IsFace(triangle, points)) { // O(n)
  321.                 this->IsProcessed = true; //??
  322.                 return point;
  323.             }
  324.         }
  325.     }
  326. }
  327.  
  328. template <class Triangle>
  329. Point Edge<Triangle>::PivotAroundEdge(std::vector<Point> &points) { // O(n^2)
  330.     assert(points.size() > 2); // не должно быть совпад
  331.     Point p1 = this->p1;
  332.     Point p2 = this->p2;
  333.     double current_angle = 0;
  334.     for (auto point: points) {
  335.         if ((point != p1 && point != p2)) {
  336.             Edge<Triangle> this_edge = *this;
  337.             Triangle triangle (this_edge, point);
  338.             if (IsFace(triangle, points)) { // O(n)
  339.                 return point;
  340.             }
  341.         }
  342.     }
  343. }
  344.  
  345.  
  346. bool IsNotUsedEdges(const std::vector<Edge<Triangle>>& edges) {
  347.     bool result = true;
  348.     for (auto edge: edges) {
  349.         result = result && edge.IsProcessed;
  350.     }
  351.     return  !result;
  352. }
  353.  
  354. template <class T>
  355. bool IsIn(const T& myelement, std::vector<T>& elements) {
  356.     for (int i = 0; i < elements.size(); ++i) {
  357.         if (myelement == elements[i]) {
  358.             elements[i].IsProcessed = true;
  359.             return true;
  360.         }
  361.     }
  362.     return  false;
  363. }
  364.  
  365.  
  366. void GiftWrapping(std::vector<Point>& points, std::vector<Triangle>& faces) {
  367.     Triangle t = FindtTriangleOnHull(points);
  368.     faces.push_back(t);
  369.     std::vector<Edge<Triangle>> edges = t.GetEdges();
  370.     while (IsNotUsedEdges(edges)) { // O(n)
  371.         Edge<Triangle>& newedge = edges.back();
  372.         if (!newedge.IsProcessed) {
  373.             Point pivot = newedge.PivotAroundEdge(points, newedge.GetForbiddenPoint());
  374.             Triangle newtriangle (newedge, pivot); //O(n)
  375.             for (Edge<Triangle> triangles_edge: newtriangle.GetEdges()) {
  376.                 if (!IsIn(triangles_edge, edges)) {
  377.                     edges.push_back(triangles_edge);
  378.                 }
  379.             }
  380.             faces.push_back(newtriangle);
  381.         }
  382.     }
  383.  
  384. }
  385.  
  386. int main() {
  387.  
  388. //  Point p1 (1,0,0,0);
  389. //  Point p2 (0,1,0,1);
  390. //  Point p3 (0,0,1,2);
  391. //  Point p4 (0,0,0,3);
  392. //
  393. //  std::vector<Point> points = {p1,p2,p3,p4};
  394. //  std::vector<Triangle> faces;
  395. //
  396. //  GiftWrapping(points, faces);
  397.  
  398.     int m; // число тестов
  399.     std::cin>>m;
  400.  
  401.     for (int i = 0; i < m; ++i) {
  402.         int n; // число точек
  403.         std::cin>>n;
  404.         std::vector<Point> points;
  405.         std::vector<Triangle> faces;
  406.         for (int j = 0; j < n; ++j) {
  407.             int x,y,z;
  408.             std::cin>>x>>y>>z;
  409.             points.emplace_back(Point(x,y,z,j));
  410.         }
  411.         GiftWrapping(points, faces);
  412.         std::cout<<faces.size()<<std::endl;
  413.         for (auto face: faces) {
  414.             std::cout<<3<<' ';
  415.             for (auto point: face.PointsInProperOrder(points)) {
  416.                 std::cout<<point.number<<' ';
  417.             }
  418.             std::cout<<'\n';
  419.         }
  420.     }
  421.  
  422.  
  423.     return  0;
  424. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement