smatskevich

Seminar5

Feb 12th, 2026
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.54 KB | None | 0 0
  1. // Geometry3D.hpp
  2.  
  3. #pragma once
  4.  
  5. #include <cmath>
  6. #include <iostream>
  7.  
  8. using ld = long double;
  9.  
  10. using namespace std;
  11.  
  12. struct Point { ld x; ld y; ld z; };
  13. struct Vector {
  14.   ld x; ld y; ld z;
  15.   ld Len() const { return sqrt(x * x + y * y + z * z); }
  16.   ld Len2() const { return x * x + y * y + z * z; }
  17.   void Normalize() { ld len = Len(); x /= len; y /= len; z /= len; }
  18. };
  19.  
  20. Point operator+(const Point& p, const Vector& v) { return {p.x + v.x, p.y + v.y, p.z + v.z}; }
  21. Point operator+(const Vector& v, const Point& p) { return {p.x + v.x, p.y + v.y, p.z + v.z}; }
  22. Point operator-(const Point& p, const Vector& v) { return {p.x - v.x, p.y - v.y, p.z - v.z}; }
  23. Vector operator-(const Point& p1, const Point& p2) { return {p1.x - p2.x, p1.y - p2.y, p1.z - p2.z}; }
  24. Vector operator+(const Vector& v1, const Vector& v2) { return {v1.x + v2.x, v1.y + v2.y, v1.z + v2.z};}
  25. Vector operator-(const Vector& v1, const Vector& v2) { return {v1.x - v2.x, v1.y - v2.y, v1.z - v2.z}; }
  26. Vector operator*(const Vector& v, ld k) { return {k * v.x, k * v.y, k * v.z}; }
  27. Vector operator*(ld k, const Vector& v) { return {v.x * k, v.y * k, v.z * k}; }
  28. Vector operator/(const Vector& v, ld k) { return {v.x / k, v.y / k, v.z / k}; }
  29. ld DotProduct(const Vector& v1, const Vector& v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; }
  30. Vector CrossProduct(const Vector& v1, const Vector& v2) {
  31.   return {v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x};
  32. }
  33. istream& operator>>(istream& in, Point& v) { in >> v.x >> v.y >> v.z; return in; }
  34. istream& operator>>(istream& in, Vector& v) { in >> v.x >> v.y >> v.z; return in; }
  35. ostream& operator<<(ostream& out, const Point& v) { out << v.x << " " << v.y << " " << v.z; return out; }
  36. ostream& operator<<(ostream& out, const Vector& v) { out << v.x << " " << v.y << " " << v.z; return out; }
  37.  
  38.  
  39. // --------------------------------------------------------------------------------------------------------
  40. // DCEL.hpp
  41.  
  42. #pragma once
  43.  
  44. #include "Geometry3D.hpp"
  45.  
  46. #include <vector>
  47. #include <memory>
  48. #include <functional>
  49.  
  50. using namespace std;
  51.  
  52. // Forward declarations
  53. struct HalfEdge;
  54. struct Vertex;
  55. struct Face;
  56.  
  57. // Vertex structure - represents a point in the DCEL
  58. struct Vertex : public Point {
  59.   HalfEdge* incident_edge = nullptr;  // One of the half-edges originating from this vertex
  60.   int index = -1;  // Index in the vertices array
  61.  
  62.   Vertex() = default;
  63.   Vertex(ld x_, ld y_, ld z_) { x = x_; y = y_; z = z_; }
  64.   Vertex(const Point& p) { x = p.x; y = p.y; z = p.z; }
  65. };
  66.  
  67. // HalfEdge structure - the main component of DCEL
  68. struct HalfEdge {
  69.   Vertex* origin = nullptr;      // Origin vertex of this half-edge
  70.   HalfEdge* twin = nullptr;      // Twin half-edge (opposite direction)
  71.   HalfEdge* next = nullptr;      // Next half-edge in the face (counter-clockwise)
  72.   HalfEdge* prev = nullptr;      // Previous half-edge in the face
  73.   Face* incident_face = nullptr; // Face to the left of this half-edge
  74.   int index = -1;                // Index in the edges array
  75.  
  76.   // Get the destination vertex
  77.   Vertex* destination() const {
  78.     return twin ? twin->origin : nullptr;
  79.   }
  80. };
  81.  
  82. // Face structure - represents a polygon face
  83. struct Face {
  84.   HalfEdge* outer_edge = nullptr;  // One of the half-edges on the outer boundary
  85.   vector<HalfEdge*> inner_edges;   // Half-edges on inner boundaries (holes)
  86.   int index = -1;                  // Index in the faces array
  87.   bool is_outer = false;           // True if this is the unbounded outer face
  88.  
  89.   // Calculate the number of edges in this face
  90.   int EdgeCount() const {
  91.     if (!outer_edge) return 0;
  92.     int count = 0;
  93.     HalfEdge* e = outer_edge;
  94.     do {
  95.       count++;
  96.       e = e->next;
  97.     } while (e && e != outer_edge);
  98.     return count;
  99.   }
  100.  
  101.   // Get all vertices of this face
  102.   vector<Vertex*> GetVertices() const {
  103.     vector<Vertex*> result;
  104.     if (!outer_edge) return result;
  105.     HalfEdge* e = outer_edge;
  106.     do {
  107.       result.push_back(e->origin);
  108.       e = e->next;
  109.     } while (e && e != outer_edge);
  110.     return result;
  111.   }
  112.  
  113.   // Calculate the normal vector of the face (assuming planar face)
  114.   Vector Normal() const {
  115.     if (!outer_edge || !outer_edge->next) return {0, 0, 0};
  116.     Vertex* v0 = outer_edge->origin;
  117.     Vertex* v1 = outer_edge->destination();
  118.     Vertex* v2 = outer_edge->next->destination();
  119.     if (!v0 || !v1 || !v2) return {0, 0, 0};
  120.     Vector e1 = *v1 - *v0;
  121.     Vector e2 = *v2 - *v0;
  122.     return CrossProduct(e1, e2);
  123.   }
  124. };
  125.  
  126. // DCEL class - Doubly Connected Edge List
  127. class DCEL {
  128.  public:
  129.   DCEL() = default;
  130.  
  131.   // Accessors
  132.   const vector<unique_ptr<HalfEdge>>& Edges() const { return edges_; }
  133.   const vector<unique_ptr<Vertex>>& Vertices() const { return vertices_; }
  134.   const vector<unique_ptr<Face>>& Faces() const { return faces_; }
  135.  
  136.   size_t NumEdges() const { return edges_.size(); }
  137.   size_t NumVertices() const { return vertices_.size(); }
  138.   size_t NumFaces() const { return faces_.size(); }
  139.  
  140.   // Create a new vertex
  141.   Vertex* CreateVertex(ld x, ld y, ld z) {
  142.     auto v = make_unique<Vertex>(x, y, z);
  143.     v->index = static_cast<int>(vertices_.size());
  144.     Vertex* ptr = v.get();
  145.     vertices_.push_back(std::move(v));
  146.     return ptr;
  147.   }
  148.  
  149.   Vertex* CreateVertex(const Point& p) {
  150.     return CreateVertex(p.x, p.y, p.z);
  151.   }
  152.  
  153.   // Create a new half-edge pair (edge and its twin)
  154.   pair<HalfEdge*, HalfEdge*> CreateEdgePair() {
  155.     auto e1 = make_unique<HalfEdge>();
  156.     auto e2 = make_unique<HalfEdge>();
  157.    
  158.     e1->index = static_cast<int>(edges_.size());
  159.     e2->index = static_cast<int>(edges_.size() + 1);
  160.    
  161.     e1->twin = e2.get();
  162.     e2->twin = e1.get();
  163.    
  164.     HalfEdge* ptr1 = e1.get();
  165.     HalfEdge* ptr2 = e2.get();
  166.    
  167.     edges_.push_back(std::move(e1));
  168.     edges_.push_back(std::move(e2));
  169.    
  170.     return {ptr1, ptr2};
  171.   }
  172.  
  173.   // Create a new face
  174.   Face* CreateFace() {
  175.     auto f = make_unique<Face>();
  176.     f->index = static_cast<int>(faces_.size());
  177.     Face* ptr = f.get();
  178.     faces_.push_back(std::move(f));
  179.     return ptr;
  180.   }
  181.  
  182.   // Connect half-edges in sequence (sets next/prev pointers)
  183.   static void ConnectEdges(HalfEdge* e1, HalfEdge* e2) {
  184.     if (e1) e1->next = e2;
  185.     if (e2) e2->prev = e1;
  186.   }
  187.  
  188.   // Set the origin of a half-edge and update vertex's incident edge if needed
  189.   static void SetOrigin(HalfEdge* edge, Vertex* vertex) {
  190.     if (!edge) return;
  191.     edge->origin = vertex;
  192.     if (vertex && !vertex->incident_edge) {
  193.       vertex->incident_edge = edge;
  194.     }
  195.   }
  196.  
  197.   // Set the face for a half-edge and update face's outer edge if needed
  198.   static void SetFace(HalfEdge* edge, Face* face) {
  199.     if (!edge) return;
  200.     edge->incident_face = face;
  201.     if (face && !face->outer_edge) {
  202.       face->outer_edge = edge;
  203.     }
  204.   }
  205.  
  206.   // Set face for all edges in a cycle starting from edge
  207.   static void SetFaceForCycle(HalfEdge* start, Face* face) {
  208.     if (!start || !face) return;
  209.     HalfEdge* e = start;
  210.     do {
  211.       e->incident_face = face;
  212.       e = e->next;
  213.     } while (e && e != start);
  214.     face->outer_edge = start;
  215.   }
  216.  
  217.   // Build a triangular face from three vertices
  218.   Face* BuildTriangle(Vertex* v0, Vertex* v1, Vertex* v2) {
  219.     auto [e01, e10] = CreateEdgePair();
  220.     auto [e12, e21] = CreateEdgePair();
  221.     auto [e20, e02] = CreateEdgePair();
  222.    
  223.     // Set origins
  224.     SetOrigin(e01, v0);
  225.     SetOrigin(e10, v1);
  226.     SetOrigin(e12, v1);
  227.     SetOrigin(e21, v2);
  228.     SetOrigin(e20, v2);
  229.     SetOrigin(e02, v0);
  230.    
  231.     // Connect edges for the inner face (counter-clockwise: v0 -> v1 -> v2)
  232.     ConnectEdges(e01, e12);
  233.     ConnectEdges(e12, e20);
  234.     ConnectEdges(e20, e01);
  235.    
  236.     // Create and set the face
  237.     Face* face = CreateFace();
  238.     SetFaceForCycle(e01, face);
  239.    
  240.     return face;
  241.   }
  242.  
  243.   // Build a polygon face from a list of vertices
  244.   Face* BuildPolygon(const vector<Vertex*>& vertices) {
  245.     if (vertices.size() < 3) return nullptr;
  246.    
  247.     size_t n = vertices.size();
  248.     vector<HalfEdge*> inner_edges(n);
  249.     vector<HalfEdge*> outer_edges(n);
  250.    
  251.     // Create all edge pairs
  252.     for (size_t i = 0; i < n; ++i) {
  253.       auto [inner, outer] = CreateEdgePair();
  254.       inner_edges[i] = inner;
  255.       outer_edges[i] = outer;
  256.     }
  257.    
  258.     // Set origins and connect edges
  259.     for (size_t i = 0; i < n; ++i) {
  260.       size_t next_i = (i + 1) % n;
  261.      
  262.       SetOrigin(inner_edges[i], vertices[i]);
  263.       SetOrigin(outer_edges[i], vertices[next_i]);
  264.      
  265.       ConnectEdges(inner_edges[i], inner_edges[next_i]);
  266.       ConnectEdges(outer_edges[next_i], outer_edges[i]);
  267.     }
  268.    
  269.     // Create and set the face
  270.     Face* face = CreateFace();
  271.     SetFaceForCycle(inner_edges[0], face);
  272.    
  273.     return face;
  274.   }
  275.  
  276.   // Iterate over all half-edges around a vertex (outgoing edges)
  277.   void ForEachEdgeAroundVertex(Vertex* v, const function<void(HalfEdge*)>& func) const {
  278.     if (!v || !v->incident_edge) return;
  279.     HalfEdge* start = v->incident_edge;
  280.     HalfEdge* e = start;
  281.     do {
  282.       func(e);
  283.       if (!e->twin) break;
  284.       e = e->twin->next;
  285.     } while (e && e != start);
  286.   }
  287.  
  288.   // Iterate over all half-edges of a face
  289.   void ForEachEdgeOfFace(Face* f, const function<void(HalfEdge*)>& func) const {
  290.     if (!f || !f->outer_edge) return;
  291.     HalfEdge* start = f->outer_edge;
  292.     HalfEdge* e = start;
  293.     do {
  294.       func(e);
  295.       e = e->next;
  296.     } while (e && e != start);
  297.   }
  298.  
  299.   // Get all faces adjacent to a vertex
  300.   vector<Face*> GetAdjacentFaces(Vertex* v) const {
  301.     vector<Face*> result;
  302.     ForEachEdgeAroundVertex(v, [&result](HalfEdge* e) {
  303.       if (e->incident_face && !e->incident_face->is_outer) {
  304.         result.push_back(e->incident_face);
  305.       }
  306.     });
  307.     return result;
  308.   }
  309.  
  310.   // Get all vertices adjacent to a vertex
  311.   vector<Vertex*> GetAdjacentVertices(Vertex* v) const {
  312.     vector<Vertex*> result;
  313.     ForEachEdgeAroundVertex(v, [&result](HalfEdge* e) {
  314.       if (e->destination()) {
  315.         result.push_back(e->destination());
  316.       }
  317.     });
  318.     return result;
  319.   }
  320.  
  321.   // Check if the DCEL is valid (basic consistency checks)
  322.   bool IsValid() const {
  323.     for (const auto& e : edges_) {
  324.       // Check twin relationship
  325.       if (!e->twin || e->twin->twin != e.get()) {
  326.         return false;
  327.       }
  328.       // Check next/prev relationship
  329.       if (e->next && e->next->prev != e.get()) {
  330.         return false;
  331.       }
  332.       if (e->prev && e->prev->next != e.get()) {
  333.         return false;
  334.       }
  335.     }
  336.     return true;
  337.   }
  338.  
  339.   // Clear all data
  340.   void Clear() {
  341.     edges_.clear();
  342.     vertices_.clear();
  343.     faces_.clear();
  344.   }
  345.  
  346.  private:
  347.   vector<unique_ptr<HalfEdge>> edges_;
  348.   vector<unique_ptr<Vertex>> vertices_;
  349.   vector<unique_ptr<Face>> faces_;
  350. };
  351.  
  352. // ----------------------------------------------------------------------------------------------------------------------
  353. // main.cpp
  354.  
  355. #include <algorithm>
  356. #include <array>
  357. #include <cassert>
  358. #include <climits>
  359. #include <cmath>
  360. #include <cstring>
  361. #include <iomanip>
  362. #include <iostream>
  363. #include <limits>
  364. #include <list>
  365. #include <map>
  366. #include <numeric>
  367. #include <queue>
  368. #include <random>
  369. #include <set>
  370. #include <sstream>
  371. #include <stack>
  372. #include <string>
  373. #include <tuple>
  374. #include <unordered_map>
  375. #include <unordered_set>
  376. #include <vector>
  377.  
  378. #include "DCEL.hpp"
  379.  
  380. #define all(x) x.begin(), x.end()
  381. using namespace std;
  382. using ll = long long;
  383. using ld = long double;
  384. const double eps = 1e-10;
  385.  
  386. // Test helper function
  387. void TestPassed(const string& test_name) {
  388.   cout << "[PASSED] " << test_name << endl;
  389. }
  390.  
  391. void TestFailed(const string& test_name, const string& reason) {
  392.   cout << "[FAILED] " << test_name << ": " << reason << endl;
  393. }
  394.  
  395. // Test 1: Basic vertex creation
  396. void TestVertexCreation() {
  397.   DCEL dcel;
  398.  
  399.   Vertex* v1 = dcel.CreateVertex(0.0, 0.0, 0.0);
  400.   Vertex* v2 = dcel.CreateVertex(1.0, 0.0, 0.0);
  401.   Vertex* v3 = dcel.CreateVertex(0.5, 1.0, 0.0);
  402.  
  403.   assert(dcel.NumVertices() == 3);
  404.   assert(v1->index == 0);
  405.   assert(v2->index == 1);
  406.   assert(v3->index == 2);
  407.   assert(v1->x == 0.0 && v1->y == 0.0 && v1->z == 0.0);
  408.   assert(v2->x == 1.0 && v2->y == 0.0 && v2->z == 0.0);
  409.   assert(v3->x == 0.5 && v3->y == 1.0 && v3->z == 0.0);
  410.  
  411.   TestPassed("TestVertexCreation");
  412. }
  413.  
  414. // Test 2: Edge pair creation
  415. void TestEdgePairCreation() {
  416.   DCEL dcel;
  417.  
  418.   auto [e1, e2] = dcel.CreateEdgePair();
  419.  
  420.   assert(dcel.NumEdges() == 2);
  421.   assert(e1->twin == e2);
  422.   assert(e2->twin == e1);
  423.   assert(e1->index == 0);
  424.   assert(e2->index == 1);
  425.  
  426.   TestPassed("TestEdgePairCreation");
  427. }
  428.  
  429. // Test 3: Face creation
  430. void TestFaceCreation() {
  431.   DCEL dcel;
  432.  
  433.   Face* f = dcel.CreateFace();
  434.  
  435.   assert(dcel.NumFaces() == 1);
  436.   assert(f->index == 0);
  437.   assert(f->outer_edge == nullptr);
  438.  
  439.   TestPassed("TestFaceCreation");
  440. }
  441.  
  442. // Test 4: Building a triangle
  443. void TestBuildTriangle() {
  444.   DCEL dcel;
  445.  
  446.   Vertex* v0 = dcel.CreateVertex(0.0, 0.0, 0.0);
  447.   Vertex* v1 = dcel.CreateVertex(1.0, 0.0, 0.0);
  448.   Vertex* v2 = dcel.CreateVertex(0.5, 1.0, 0.0);
  449.  
  450.   Face* face = dcel.BuildTriangle(v0, v1, v2);
  451.  
  452.   assert(face != nullptr);
  453.   assert(face->outer_edge != nullptr);
  454.   assert(face->EdgeCount() == 3);
  455.  
  456.   // Check that all vertices are in the face
  457.   vector<Vertex*> face_vertices = face->GetVertices();
  458.   assert(face_vertices.size() == 3);
  459.  
  460.   // Check that the cycle is closed
  461.   HalfEdge* start = face->outer_edge;
  462.   HalfEdge* e = start;
  463.   int count = 0;
  464.   do {
  465.     assert(e->incident_face == face);
  466.     assert(e->next != nullptr);
  467.     assert(e->prev != nullptr);
  468.     assert(e->next->prev == e);
  469.     assert(e->prev->next == e);
  470.     e = e->next;
  471.     count++;
  472.   } while (e != start && count < 10);
  473.   assert(count == 3);
  474.  
  475.   TestPassed("TestBuildTriangle");
  476. }
  477.  
  478. // Test 5: Building a polygon (square)
  479. void TestBuildPolygon() {
  480.   DCEL dcel;
  481.  
  482.   Vertex* v0 = dcel.CreateVertex(0.0, 0.0, 0.0);
  483.   Vertex* v1 = dcel.CreateVertex(1.0, 0.0, 0.0);
  484.   Vertex* v2 = dcel.CreateVertex(1.0, 1.0, 0.0);
  485.   Vertex* v3 = dcel.CreateVertex(0.0, 1.0, 0.0);
  486.  
  487.   Face* face = dcel.BuildPolygon({v0, v1, v2, v3});
  488.  
  489.   assert(face != nullptr);
  490.   assert(face->EdgeCount() == 4);
  491.  
  492.   vector<Vertex*> face_vertices = face->GetVertices();
  493.   assert(face_vertices.size() == 4);
  494.  
  495.   TestPassed("TestBuildPolygon");
  496. }
  497.  
  498. // Test 6: Edge connectivity
  499. void TestEdgeConnectivity() {
  500.   DCEL dcel;
  501.  
  502.   auto [e1, e2] = dcel.CreateEdgePair();
  503.   auto [e3, e4] = dcel.CreateEdgePair();
  504.  
  505.   DCEL::ConnectEdges(e1, e3);
  506.  
  507.   assert(e1->next == e3);
  508.   assert(e3->prev == e1);
  509.  
  510.   TestPassed("TestEdgeConnectivity");
  511. }
  512.  
  513. // Test 7: Vertex incident edge
  514. void TestVertexIncidentEdge() {
  515.   DCEL dcel;
  516.  
  517.   Vertex* v = dcel.CreateVertex(0.0, 0.0, 0.0);
  518.   auto [e1, e2] = dcel.CreateEdgePair();
  519.  
  520.   DCEL::SetOrigin(e1, v);
  521.  
  522.   assert(e1->origin == v);
  523.   assert(v->incident_edge == e1);
  524.  
  525.   TestPassed("TestVertexIncidentEdge");
  526. }
  527.  
  528. // Test 8: Face normal calculation
  529. void TestFaceNormal() {
  530.   DCEL dcel;
  531.  
  532.   // Create a triangle in the XY plane
  533.   Vertex* v0 = dcel.CreateVertex(0.0, 0.0, 0.0);
  534.   Vertex* v1 = dcel.CreateVertex(1.0, 0.0, 0.0);
  535.   Vertex* v2 = dcel.CreateVertex(0.0, 1.0, 0.0);
  536.  
  537.   Face* face = dcel.BuildTriangle(v0, v1, v2);
  538.   Vector normal = face->Normal();
  539.  
  540.   // Normal should point in Z direction (positive or negative depending on winding)
  541.   assert(abs(normal.x) < eps);
  542.   assert(abs(normal.y) < eps);
  543.   assert(abs(normal.z) > eps);
  544.  
  545.   TestPassed("TestFaceNormal");
  546. }
  547.  
  548. // Test 9: DCEL validity check
  549. void TestDCELValidity() {
  550.   DCEL dcel;
  551.  
  552.   Vertex* v0 = dcel.CreateVertex(0.0, 0.0, 0.0);
  553.   Vertex* v1 = dcel.CreateVertex(1.0, 0.0, 0.0);
  554.   Vertex* v2 = dcel.CreateVertex(0.5, 1.0, 0.0);
  555.  
  556.   dcel.BuildTriangle(v0, v1, v2);
  557.  
  558.   assert(dcel.IsValid());
  559.  
  560.   TestPassed("TestDCELValidity");
  561. }
  562.  
  563. // Test 10: Destination vertex
  564. void TestDestinationVertex() {
  565.   DCEL dcel;
  566.  
  567.   Vertex* v0 = dcel.CreateVertex(0.0, 0.0, 0.0);
  568.   Vertex* v1 = dcel.CreateVertex(1.0, 0.0, 0.0);
  569.  
  570.   auto [e1, e2] = dcel.CreateEdgePair();
  571.   DCEL::SetOrigin(e1, v0);
  572.   DCEL::SetOrigin(e2, v1);
  573.  
  574.   assert(e1->destination() == v1);
  575.   assert(e2->destination() == v0);
  576.  
  577.   TestPassed("TestDestinationVertex");
  578. }
  579.  
  580. // Test 11: Adjacent vertices
  581. void TestAdjacentVertices() {
  582.   DCEL dcel;
  583.  
  584.   Vertex* v0 = dcel.CreateVertex(0.0, 0.0, 0.0);
  585.   Vertex* v1 = dcel.CreateVertex(1.0, 0.0, 0.0);
  586.   Vertex* v2 = dcel.CreateVertex(0.5, 1.0, 0.0);
  587.  
  588.   dcel.BuildTriangle(v0, v1, v2);
  589.  
  590.   // v0 should be adjacent to v1 and v2
  591.   vector<Vertex*> adjacent = dcel.GetAdjacentVertices(v0);
  592.   assert(adjacent.size() >= 1);  // At least one adjacent vertex
  593.  
  594.   TestPassed("TestAdjacentVertices");
  595. }
  596.  
  597. // Test 12: Clear DCEL
  598. void TestClearDCEL() {
  599.   DCEL dcel;
  600.  
  601.   dcel.CreateVertex(0.0, 0.0, 0.0);
  602.   dcel.CreateVertex(1.0, 0.0, 0.0);
  603.   dcel.CreateEdgePair();
  604.   dcel.CreateFace();
  605.  
  606.   assert(dcel.NumVertices() == 2);
  607.   assert(dcel.NumEdges() == 2);
  608.   assert(dcel.NumFaces() == 1);
  609.  
  610.   dcel.Clear();
  611.  
  612.   assert(dcel.NumVertices() == 0);
  613.   assert(dcel.NumEdges() == 0);
  614.   assert(dcel.NumFaces() == 0);
  615.  
  616.   TestPassed("TestClearDCEL");
  617. }
  618.  
  619. // Test 13: ForEachEdgeOfFace
  620. void TestForEachEdgeOfFace() {
  621.   DCEL dcel;
  622.  
  623.   Vertex* v0 = dcel.CreateVertex(0.0, 0.0, 0.0);
  624.   Vertex* v1 = dcel.CreateVertex(1.0, 0.0, 0.0);
  625.   Vertex* v2 = dcel.CreateVertex(0.5, 1.0, 0.0);
  626.  
  627.   Face* face = dcel.BuildTriangle(v0, v1, v2);
  628.  
  629.   int edge_count = 0;
  630.   dcel.ForEachEdgeOfFace(face, [&edge_count](HalfEdge* e) {
  631.     edge_count++;
  632.     assert(e != nullptr);
  633.   });
  634.  
  635.   assert(edge_count == 3);
  636.  
  637.   TestPassed("TestForEachEdgeOfFace");
  638. }
  639.  
  640. // Test 14: Pentagon polygon
  641. void TestPentagon() {
  642.   DCEL dcel;
  643.  
  644.   // Create a regular pentagon
  645.   vector<Vertex*> vertices;
  646.   for (int i = 0; i < 5; ++i) {
  647.     ld angle = 2.0 * M_PI * i / 5.0;
  648.     vertices.push_back(dcel.CreateVertex(cos(angle), sin(angle), 0.0));
  649.   }
  650.  
  651.   Face* face = dcel.BuildPolygon(vertices);
  652.  
  653.   assert(face != nullptr);
  654.   assert(face->EdgeCount() == 5);
  655.   assert(dcel.IsValid());
  656.  
  657.   TestPassed("TestPentagon");
  658. }
  659.  
  660. // Test 15: Multiple triangles
  661. void TestMultipleTriangles() {
  662.   DCEL dcel;
  663.  
  664.   // Create two separate triangles
  665.   Vertex* v0 = dcel.CreateVertex(0.0, 0.0, 0.0);
  666.   Vertex* v1 = dcel.CreateVertex(1.0, 0.0, 0.0);
  667.   Vertex* v2 = dcel.CreateVertex(0.5, 1.0, 0.0);
  668.  
  669.   Vertex* v3 = dcel.CreateVertex(2.0, 0.0, 0.0);
  670.   Vertex* v4 = dcel.CreateVertex(3.0, 0.0, 0.0);
  671.   Vertex* v5 = dcel.CreateVertex(2.5, 1.0, 0.0);
  672.  
  673.   Face* face1 = dcel.BuildTriangle(v0, v1, v2);
  674.   Face* face2 = dcel.BuildTriangle(v3, v4, v5);
  675.  
  676.   assert(face1 != nullptr);
  677.   assert(face2 != nullptr);
  678.   assert(dcel.NumFaces() == 2);
  679.   assert(dcel.NumVertices() == 6);
  680.   assert(dcel.IsValid());
  681.  
  682.   TestPassed("TestMultipleTriangles");
  683. }
  684.  
  685. void RunAllTests() {
  686.   cout << "Running DCEL tests..." << endl;
  687.   cout << "========================" << endl;
  688.  
  689.   TestVertexCreation();
  690.   TestEdgePairCreation();
  691.   TestFaceCreation();
  692.   TestBuildTriangle();
  693.   TestBuildPolygon();
  694.   TestEdgeConnectivity();
  695.   TestVertexIncidentEdge();
  696.   TestFaceNormal();
  697.   TestDCELValidity();
  698.   TestDestinationVertex();
  699.   TestAdjacentVertices();
  700.   TestClearDCEL();
  701.   TestForEachEdgeOfFace();
  702.   TestPentagon();
  703.   TestMultipleTriangles();
  704.  
  705.   cout << "========================" << endl;
  706.   cout << "All tests passed!" << endl;
  707. }
  708.  
  709. void Solve() {
  710.   RunAllTests();
  711. }
  712.  
  713. int main() {
  714.   ios::sync_with_stdio(false);
  715.   cin.tie(nullptr);
  716.   cout.tie(nullptr);
  717.   Solve();
  718.   return 0;
  719. }
  720.  
Advertisement
Add Comment
Please, Sign In to add comment