Advertisement
Tucancitto

Proiect AF - Triangularea unui poligon

Dec 29th, 2020 (edited)
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.58 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <algorithm>
  4. #include <vector>
  5. #include <iomanip>
  6. using namespace std;
  7.  
  8. #define x first
  9. #define y second
  10.  
  11. #define for_nrVarfuri for (int i = 0; i < nrVf; i++)
  12. #define for_(x) for(auto& it : x)
  13.  
  14. typedef pair<float, float> Punct;
  15. typedef pair<Punct, Punct> Segment;
  16.  
  17. void citire(int& nrVf, vector<Punct>& vf)
  18. {
  19.     ifstream fin("triangulare.in");
  20.  
  21.     fin >> nrVf;
  22.     vf.resize(nrVf);
  23.  
  24.     for_(vf)
  25.         fin >> it.x >> it.y;
  26.  
  27.     fin.close();
  28. }
  29.  
  30. float Det(const Punct& p1, const Punct& p2, const Punct& p3)
  31. {
  32.     return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
  33. }
  34.  
  35. bool EsteInPoligon(int nrVf, vector<Punct> vf, const Punct& p)
  36. {
  37.     Punct q(1000000, rand() % 1000000);
  38.  
  39.     bool este = false;
  40.     for_nrVarfuri
  41.     {
  42.         int j = (i + 1) % nrVf;
  43.  
  44.         if (Det(p, vf[i], vf[j]) * Det(q, vf[i], vf[j]) > 0 && Det(vf[i], p, q) * Det(vf[j], p, q) < 0)
  45.             este ^= true;
  46.     }
  47.  
  48.     return este;
  49. }
  50.  
  51. bool IntersectieIntervale(double st1, double dr1, double st2, double dr2)
  52. {
  53.     if (st1 > st2)
  54.     {
  55.         swap(st1, st2);
  56.         swap(dr1, dr2);
  57.     }
  58.  
  59.     return dr1 - st2 > 0;
  60. }
  61.  
  62. bool IntersectieSegmente(const Segment& s1, const Segment& s2)
  63. {
  64.     if (!Det(s1.x, s1.y, s2.x) && !Det(s1.x, s1.y, s2.y))
  65.     {
  66.         if (IntersectieIntervale(min(s1.x.x, s1.y.x), max(s1.x.x, s1.y.x), min(s2.x.x, s2.y.x), max(s2.x.x, s2.y.x))
  67.             || IntersectieIntervale(min(s1.x.y, s1.y.y), max(s1.x.y, s1.y.y), min(s2.x.y, s2.y.y), max(s2.x.y, s2.y.y)))
  68.             return true;
  69.         else
  70.             return false;
  71.     }
  72.  
  73.     return (Det(s1.x, s1.y, s2.x) * Det(s1.x, s1.y, s2.y) < 0 && Det(s2.x, s2.y, s1.x) * Det(s2.x, s2.y, s1.y) < 0);
  74. }
  75.  
  76. bool VerificareSegment(int nrVf, vector<Punct> vf, vector<Punct> tr, Segment segmCurent)
  77. {
  78.     for_nrVarfuri
  79.         if (IntersectieSegmente(segmCurent, Segment(vf[i], vf[(i + 1) % nrVf])))
  80.             return false;
  81.  
  82.     for_(tr)
  83.         if (IntersectieSegmente(segmCurent, Segment(vf[it.x], vf[it.y])))
  84.             return false;
  85.  
  86.     Punct q((segmCurent.x.x + segmCurent.y.x) / 2, (segmCurent.x.y + segmCurent.y.y) / 2);
  87.     return EsteInPoligon(nrVf, vf, q);
  88. }
  89.  
  90. void parcurgere(int nrVf, vector<Punct> vf, vector<Punct>& tr)
  91. {
  92.     for_nrVarfuri
  93.         for (int j = (i + 2) % nrVf; (j + 1) % nrVf != i; j = (j + 1) % nrVf)
  94.             if (VerificareSegment(nrVf, vf, tr, Segment(vf[i], vf[j])))
  95.                 tr.push_back({ min(i, j), max(i, j) });
  96. }
  97.  
  98. void afisare(int nrVf, vector<Punct> vf, vector<Punct> tr)
  99. {
  100.     ofstream fout("triangulare.out");
  101.  
  102.     int contor = 1;
  103.     for_(vf)
  104.         fout << "Punctul " << setw(2) << contor++ << " are coordonatele (" << setw(3) << it.x << ", " << setw(3) << it.y << ") \n";
  105.  
  106.     if (nrVf < 3)
  107.         fout << "Punctele introduse nu pot forma un poligon. Introduceti o valoare strict mai mare decat 3. \n";
  108.     else
  109.         if (nrVf == 3)
  110.         {
  111.             if (Det(vf[0], vf[1], vf[2]))
  112.                 fout << "Punctele introduse formeaza un triunghi. \n";
  113.             else
  114.                 fout << "Punctele introduse nu formeaza un triunghi. \n";
  115.         }
  116.         else
  117.         {
  118.             contor = 1;
  119.             fout << "\nIndicii varfurilor care formeaza segmentul respectiv: \n";
  120.             for_(tr)
  121.                 fout << "Segmentul " << setw(2) << contor++ << " are capetele in varfurile cu indicii " << setw(2) << it.x + 1 << ' ' << setw(2) << it.y + 1 << " \n";
  122.         }
  123. }
  124.  
  125. int main()
  126. {
  127.     srand(time(NULL));
  128.     int nrVarfuri;
  129.     vector<Punct> vf, triangulare;
  130.  
  131.     citire(nrVarfuri, vf);
  132.     parcurgere(nrVarfuri, vf, triangulare);
  133.     sort(triangulare.begin(), triangulare.end());
  134.     afisare(nrVarfuri, vf, triangulare);
  135.  
  136.     return 0;
  137. }
  138.  
  139. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  140.  
  141. #include <iostream>
  142. #include <fstream>
  143. #include <algorithm>
  144. #include <vector>
  145. #include <iomanip>
  146. using namespace std;
  147.  
  148. ifstream fin("triangulare.in");
  149. ofstream fout("triangulare.out");
  150.  
  151. const double Zero = 1.0e-7; //10^(-7)
  152.  
  153. typedef pair<double, double> Punct; // struct Punct { double first, double second };
  154. typedef pair<Punct, Punct> Segment; // struct Segment { Punct first, Punct second };
  155.  
  156. int nrVarfuri;
  157. vector<Punct> poligon, triangulare;
  158.  
  159. bool EsteZero(const double& x)
  160. {
  161.     //Din cauza tipului double este posibil sa nu obtinem 0, ci rezultate apropiate de zero (de exemplu: 0.000012).
  162.     //Vom face aproximarea lui Zero cu 10^(-7).
  163.  
  164.     return fabs(x) < Zero;
  165. }
  166.  
  167. double Determinant(const Punct& p1, const Punct& p2, const Punct& p3)
  168. {
  169.     /*
  170.         Determinantul se poate calcula dupa formula
  171.         | xA yA 1 |
  172.         | xB yB 1 |
  173.         | xC yC 1 |
  174.  
  175.         in cazul nostru:
  176.  
  177.         | p1.first  p1.second   1 |
  178.         | p2.first  p2.second   1 |
  179.         | p3.first  p3.second   1 |.
  180.  
  181.         Putem calcula acest determinat punand conditia ca punctul C sa se situeze pe ecuatia dreptei determinata de punctele A, B:
  182.         yC - yA     xC - xA
  183.         -------- = ---------, relatie echivalenta cu (yC - yA)*(xB - xA) = (xC - xA)*(yB - yA), trecem ce se afla in membrul drept in membrul stang cu semn
  184.         yB - yA     xB - xA                                                                     schimbat si obtinem relatia pe care o returnam.
  185.  
  186.         Datorita relatiei de mai sus verificam daca punctul C se afla pe ecuatia dreptei AB.
  187.  
  188.  
  189.         Altfel spus, daca relatia de mai jos este 0 (cea pe care o returnam), atunci punctele sunt coliniare, altfel nu sunt coliniare.
  190.     */
  191.  
  192.     return (p2.first - p1.first) * (p3.second - p1.second) - (p2.second - p1.second) * (p3.first - p1.first);
  193.  
  194. }
  195.  
  196. bool EsteInPoligon(const Punct& p)
  197. {
  198.     Punct q(1000000, rand() % 1000000);
  199.  
  200.     bool esteInPoligon = false;
  201.     for (int i = 0; i < nrVarfuri; i++)
  202.     {
  203.         int j = (i + 1) % nrVarfuri;
  204.  
  205.         if (Determinant(p, poligon[i], poligon[j]) * Determinant(q, poligon[i], poligon[j]) > 0
  206.             && Determinant(poligon[i], p, q) * Determinant(poligon[j], p, q) < -Zero)
  207.             esteInPoligon ^= true;
  208.     }
  209.  
  210.     return esteInPoligon;
  211. }
  212.  
  213. bool IntersectieIntervale(double stanga1, double dreapta1, double stanga2, double dreapta2)
  214. {
  215.     if (stanga1 > stanga2)
  216.     {
  217.         swap(stanga1, stanga2);
  218.         swap(dreapta1, dreapta2);
  219.     }
  220.  
  221.     return dreapta1 - stanga2 > Zero;
  222. }
  223.  
  224.  
  225. bool IntersectieSegmente(const Segment& s1, const Segment& s2)
  226. {
  227.     if (EsteZero(Determinant(s1.first, s1.second, s2.first)) && EsteZero(Determinant(s1.first, s1.second, s2.second)))
  228.     {
  229.         if (IntersectieIntervale(min(s1.first.first, s1.second.first), max(s1.first.first, s1.second.first),
  230.             min(s2.first.first, s2.second.first), max(s2.first.first, s2.second.first))
  231.             || IntersectieIntervale(min(s1.first.second, s1.second.second), max(s1.first.second, s1.second.second),
  232.                 min(s2.first.second, s2.second.second), max(s2.first.second, s2.second.second)))
  233.             return true;
  234.         else
  235.             return false;
  236.     }
  237.  
  238.     return (Determinant(s1.first, s1.second, s2.first) * Determinant(s1.first, s1.second, s2.second) < -Zero
  239.         && Determinant(s2.first, s2.second, s1.first) * Determinant(s2.first, s2.second, s1.second) < -Zero);
  240. }
  241.  
  242. bool VerificareSegment(Segment cutSegment)
  243. {
  244.     for (int i = 0; i < nrVarfuri; i++)
  245.     {
  246.         if (IntersectieSegmente(cutSegment, Segment(poligon[i], poligon[(i + 1) % nrVarfuri])))
  247.             return false;
  248.     }
  249.  
  250.     for (auto& it : triangulare)
  251.     {
  252.         if (IntersectieSegmente(cutSegment, Segment(poligon[it.first], poligon[it.second])))
  253.             return false;
  254.     }
  255.  
  256.     return EsteInPoligon(Punct((cutSegment.first.first + cutSegment.second.first) / 2,
  257.         (cutSegment.first.second + cutSegment.second.second) / 2));
  258. }
  259.  
  260. int main()
  261. {
  262.     srand(time(NULL));
  263.  
  264.     fin >> nrVarfuri;
  265.  
  266.     if (nrVarfuri < 3)
  267.     {
  268.         fout << "Punctele introduse nu pot forma un poligon. Introduceti o valoare strict mai mare decat 3. \n";
  269.         return 0;
  270.     }
  271.  
  272.     poligon.resize(nrVarfuri);
  273.  
  274.     int contor = 1;
  275.     for (auto& it : poligon)
  276.     {
  277.         fin >> it.first >> it.second;
  278.         fout << "Punctul " << setw(2) << contor++ << " are coordonatele (" << setw(3) << it.first << ", " << setw(3) << it.second << ") \n";
  279.     }
  280.  
  281.     if (nrVarfuri == 3)
  282.     {
  283.         if (Determinant(poligon[0], poligon[1], poligon[2]))
  284.             fout << "Punctele introduse formeaza un triunghi. \n";
  285.         else
  286.             fout << "Punctele introduse nu formeaza un triunghi. \n";
  287.         return 0;
  288.     }
  289.  
  290.     for (int i = 0; i < nrVarfuri; i++)
  291.     {
  292.         for (int j = (i + 2) % nrVarfuri; (j + 1) % nrVarfuri != i; j = (j + 1) % nrVarfuri)
  293.         {
  294.             if (VerificareSegment(Segment(poligon[i], poligon[j])))
  295.                 triangulare.push_back({ min(i, j), max(i, j) }); // retinem indicii capetelor acelor puncte care formeaza segmentul (in ordine crescatoare)
  296.         }
  297.     }
  298.  
  299.     sort(triangulare.begin(), triangulare.end());
  300.  
  301.     contor = 1;
  302.     fout << "\nIndicii varfurilor care formeaza segmentul respectiv: \n";
  303.     for (auto& it : triangulare)
  304.         fout << "Segmentul " << setw(2) << contor++ << " are ca si capete varfurile cu indicii " << setw(2) << it.first + 1 << ' ' << setw(2) << it.second + 1 << " \n";
  305.  
  306.     return 0;
  307. }
  308.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement