Advertisement
Guest User

cpp

a guest
Nov 21st, 2019
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.37 KB | None | 0 0
  1. #include <algorithm>
  2. #include <array>
  3. #include <chrono>
  4. #include <cmath>
  5. #include <cstdlib>
  6. #include <iostream>
  7. #include <fstream>
  8. #include <random>
  9. #include <string>
  10. #include <omp.h>
  11. #include <stdexcept>
  12. #include <tuple>
  13. #include <vector>
  14. #include <stdint.h>
  15.  
  16. using namespace std;
  17. using namespace std::chrono;
  18.  
  19. // Structure of a point in 2D plane
  20. struct Point {
  21.     float x, y;
  22. };
  23.  
  24. float computeDistance(const Point &a, const Point &b) {
  25.     return (float) sqrt(pow(a.x - b.x, 2) +
  26.                         pow(a.y - b.y, 2) * 1.0);
  27. }
  28.  
  29. void findTriangles(int i, int j, vector<vector<int>> &trianglesMatrix, vector<tuple<int, int, int>> &triangles) {
  30.     if (j > i + 1) {
  31.         int k = trianglesMatrix[i][j];
  32.         triangles.push_back(make_tuple(i, j, k));
  33.         findTriangles(i, k, trianglesMatrix, triangles);
  34.         findTriangles(k, i, trianglesMatrix, triangles);
  35.     }
  36. }
  37.  
  38. // A Dynamic programming based function to find minimum cost for convex polygon triangulation.
  39. // points: vector of points of the convex polygon in counter-clockwise order.
  40. tuple<vector<tuple<int, int, int>>, float> triangulate(const vector<Point> &points) {
  41.     int n = points.size();
  42.     float triagCost = 0.0f;
  43.     vector<vector<int>> trianglesMatrix;
  44.     vector<tuple<int, int, int>> triangles;
  45.     vector<vector<float>> distances;
  46.     distances.resize(n, vector<float>(n, 0.0));
  47.     trianglesMatrix.resize(n, vector<int>(n, -1));
  48.  
  49.     for (int diff = 0; diff < n; ++diff) {
  50.         for (int i = 0, j = diff; j < n; ++i, ++j) {
  51.             if (j < i + 2) {
  52.                 distances[i][j] = 0.0f;
  53.             } else {
  54.                 distances[i][j] = std::numeric_limits<float>::max();
  55.                 for (int k = i + 1; k < j; ++k) {
  56.                     float cost = distances[i][k] + distances[k][j] + computeDistance(points[i], points[k]) +
  57.                                  computeDistance(points[k], points[j]) + computeDistance(points[j], points[i]);
  58.                     if (distances[i][j] > cost) {
  59.                         distances[i][j] = cost;
  60.                         trianglesMatrix[i][j] = k;
  61.                     }
  62.                 }
  63.             }
  64.         }
  65.     }
  66.  
  67.     findTriangles(0, n - 1, trianglesMatrix, triangles);
  68.     triagCost = distances[0][n - 1];
  69.  
  70.     // TODO: Implement a parallel dynamic programming approach for triangulation.
  71.     // Fill variables triagCost and triangles.
  72.     // triagCost: the cost of the triangulation.
  73.     // triangles: vector of triangles. Each triangle is represented by indices (into points vector) of its corner points.
  74.  
  75.     return make_tuple(move(triangles), triagCost);
  76. }
  77.  
  78. vector<Point> readProblem(const string &inputFile) {
  79.     vector<Point> points;
  80.     ifstream bin(inputFile.c_str(), ifstream::binary);
  81.     if (bin) {
  82.         int32_t n = 0;
  83.         bin.read((char *) &n, sizeof(int32_t));
  84.         for (uint64_t p = 0; p < n; ++p) {
  85.             float x = 0.0, y = 0.0;
  86.             bin.read((char *) &x, sizeof(float));
  87.             bin.read((char *) &y, sizeof(float));
  88.             points.push_back({x, y});
  89.         }
  90.  
  91.         bin.close();
  92.     } else {
  93.         throw invalid_argument("Cannot open the input file '" + inputFile + "' to read the problem.");
  94.     }
  95.  
  96.     return points;
  97. }
  98.  
  99. void writeResult(float triagCost, const vector<tuple<int, int, int>> &triangles, const string &resultFile) {
  100.     ofstream bout(resultFile.c_str(), ofstream::binary | ofstream::trunc);
  101.     if (bout) {
  102.         bout.write((char *) &triagCost, sizeof(float));
  103.         for (const auto &triangle : triangles) {
  104.             int32_t p1, p2, p3;
  105.             tie(p1, p2, p3) = triangle;
  106.             bout.write((char *) &p1, sizeof(int32_t));
  107.             bout.write((char *) &p2, sizeof(int32_t));
  108.             bout.write((char *) &p3, sizeof(int32_t));
  109.         }
  110.  
  111.         bout.close();
  112.     } else {
  113.         throw invalid_argument("Cannot write the results, check the permissions.");
  114.     }
  115. }
  116.  
  117. void writeImage(
  118.         const vector<Point> &points,
  119.         const vector<tuple<int, int, int>> &triangles,
  120.         const string &imageFilename) {
  121.     constexpr uint32_t numOfColors = 10;
  122.     array<string, numOfColors> colors = {
  123.             "orange", "brown", "purple", "blue", "darksalmon", "yellow", "green", "red", "lime", "aqua"
  124.     };
  125.  
  126.     float minX = 10e6, maxX = -10e6, minY = 10e6, maxY = -10e6;
  127.     for (const Point &p : points) {
  128.         minX = min(minX, p.x);
  129.         maxX = max(maxX, p.x);
  130.         minY = min(minY, p.y);
  131.         maxY = max(maxY, p.y);
  132.     }
  133.  
  134.     float mult = 1600.0f / (maxX - minX), height = ceil(mult * (maxY - minY));
  135.  
  136.     ofstream im(imageFilename);
  137.     if (im) {
  138.         im << "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1600\" height=\"" << height << "\">" << endl;
  139.  
  140.         default_random_engine generator;
  141.         uniform_int_distribution<uint32_t> colorIdx(0u, numOfColors - 1u);
  142.         for (const tuple<int, int, int> &t : triangles) {
  143.             int i, j, k;
  144.             tie(i, j, k) = t;
  145.  
  146.             array<Point, 3> p{points[i], points[j], points[k]};
  147.             for (uint32_t i = 0; i < 3; ++i) {
  148.                 p[i].x = mult * (p[i].x - minX);
  149.                 p[i].y = mult * (p[i].y - minY);
  150.             }
  151.  
  152.             im << "\t<polygon points=\"" << p[0].x << "," << p[0].y << " " << p[1].x << "," << p[1].y << " " << p[2].x
  153.                << "," << p[2].y << "\" ";
  154.             im << "style=\"fill:" << colors[colorIdx(generator)] << ";stroke:black;stroke-width=0.3\"/>" << endl;
  155.         }
  156.  
  157.         for (uint32_t i = 0; i < points.size(); ++i) {
  158.             array<Point, 2> p{points[i % points.size()], points[(i + 1) % points.size()]};
  159.             for (uint32_t i = 0; i < 2; ++i) {
  160.                 p[i].x = mult * (p[i].x - minX);
  161.                 p[i].y = mult * (p[i].y - minY);
  162.             }
  163.  
  164.             im << "\t<line x1=\"" << p[0].x << "\" y1=\"" << p[0].y << "\" x2=\"" << p[1].x << "\" y2=\"" << p[1].y
  165.                << "\" ";
  166.             im << "stroke-width=\"2\" stroke=\"black\"/>" << endl;
  167.         }
  168.  
  169.         im << "</svg>" << endl;
  170.         im.close();
  171.     } else {
  172.         cerr << "Cannot write the result to svg file!" << endl;
  173.     }
  174. }
  175.  
  176. void printHelpPage(char *program) {
  177.     cout << "Triangulation of a convex polygon." << endl;
  178.     cout << endl << "Usage:" << endl;
  179.     cout << "\t" << program << " INPUT_PATH OUTPUT_PATH [options]" << endl << endl;
  180.     cout << "General options:" << endl;
  181.     cout << "\t--output-image IMAGE_PATH, -of IMAGE_PATH" << endl;
  182.     cout << "\t\tGenerates svg file demonstrating the triangulation." << endl;
  183.     cout << "\t--help, -h" << endl;
  184.     cout << "\t\tPrints this help." << endl;
  185. }
  186.  
  187. int main(int argc, char *argv[]) {
  188.     string imageFilename, inputFile, resultFile;
  189.  
  190.     if (argc == 1) {
  191.         printHelpPage(argv[0]);
  192.         return 0;
  193.     }
  194.  
  195.     for (int i = 1; i < argc; ++i) {
  196.         string parg = argv[i];
  197.         if (parg == "--help" || parg == "-h") {
  198.             printHelpPage(argv[0]);
  199.             return 0;
  200.         }
  201.  
  202.         if (parg == "--output-image" || parg == "-of") {
  203.             if (i + 1 < argc) {
  204.                 imageFilename = argv[++i];
  205.             } else {
  206.                 cerr << "Expected a filename for the output image!" << endl;
  207.                 return 1;
  208.             }
  209.         }
  210.  
  211.         if (!parg.empty() && parg[0] != '-') {
  212.             if (inputFile.empty()) {
  213.                 inputFile = parg;
  214.             } else {
  215.                 resultFile = parg;
  216.             }
  217.         }
  218.     }
  219.  
  220.     try {
  221.         high_resolution_clock::time_point start = high_resolution_clock::now();
  222.  
  223.         float criterion;
  224.         vector<tuple<int, int, int>> triangles;
  225.         const vector<Point> &points = readProblem(inputFile);
  226.  
  227.         tie(triangles, criterion) = triangulate(points);
  228.         double totalDuration = duration_cast<duration<double>>(high_resolution_clock::now() - start).count();
  229.  
  230.         if (!resultFile.empty()) {
  231.             writeResult(criterion, triangles, resultFile);
  232.         }
  233.  
  234.         if (!imageFilename.empty()) {
  235.             writeImage(points, triangles, imageFilename);
  236.         }
  237.  
  238.         cout << "Cost of triangulation: " << criterion << endl;
  239.         cout << "computational time: " << totalDuration << " s" << endl;
  240.  
  241.     } catch (exception &e) {
  242.         cerr << "Exception caught: " << e.what() << endl;
  243.         return 2;
  244.     }
  245.  
  246.     return 0;
  247. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement