graph.cpp (3684B)
1 #include "../headers/graph.hpp" 2 #include "../headers/constants.hpp" 3 #include "../headers/vertex.hpp" 4 #include "../headers/utils.hpp" 5 #include <cstddef> 6 #include <cstdint> 7 #include <raylib.h> 8 #include <stdexcept> 9 10 Graph::Graph(std::size_t edgeCount, std::size_t vertCount, uint32_t xMax, uint32_t yMax) { 11 12 if(edgeCount > 0 && vertCount <= 1) { 13 throw std::invalid_argument("This graph does not support self-loops."); 14 } 15 if(xMax <= 0 || yMax <= 0) { 16 throw std::invalid_argument("xMax and yMax must be > 0."); 17 } 18 19 20 for(std::size_t i = 0; i < vertCount; ++i) { 21 Vector2 rnd = randomPosition(xMax, yMax); 22 Vertex v {rnd,VERTEX_RENDER_SIZE}; 23 this->vertices.push_back(v); 24 } 25 for(std::size_t i = 0; i < edgeCount; ++i) { 26 std::size_t idx1 = 0; 27 std::size_t idx2 = 0; 28 // no self-edges 29 while (idx1 == idx2) { 30 idx1 = std::rand() % vertCount; 31 idx2 = std::rand() % vertCount; 32 } 33 34 Edge e {idx1, idx2, distanceSquared(vertices[idx1].position, vertices[idx2].position), i}; 35 this->edges[idx1].push_back(e); 36 this->edges[idx2].push_back(e); 37 } 38 } 39 40 std::string Graph::toString() noexcept { 41 42 std::string result = "edges: {"; 43 44 for(auto pair: this->edges) { 45 auto key = pair.first; 46 for(auto edge: edges[key]) { 47 result += edge.toString(); 48 } 49 } 50 51 result += "}"; 52 53 result += "\nvertices: {"; 54 55 for(auto vertex: this->vertices) { 56 result += vertex.toString(); 57 } 58 59 result += "}"; 60 return result; 61 } 62 63 64 void Graph::render() noexcept { 65 66 // yes, this will double draw because we track 0 -> 1 and 1 -> 0 67 68 std::vector<Edge> visited {}; 69 for(auto pair: this->edges) { 70 auto edges = this->edges[pair.first]; 71 for(auto edge: edges) { 72 std::size_t idx1 = edge.v1Index; 73 std::size_t idx2 = edge.v2Index; 74 auto v1 = vertices[idx1].position; 75 auto v2 = vertices[idx2].position; 76 if(edge.traversed) { 77 visited.push_back(edge); 78 } else { 79 DrawLineEx(v1, v2, EDGE_REDNER_SIZE,DARKERGRAY); 80 } 81 } 82 } 83 84 for(auto vertex: this->vertices) { 85 vertex.render(); 86 } 87 88 // ensure we draw visited over unvisited for better looks 89 for(auto edge: visited) { 90 std::size_t idx1 = edge.v1Index; 91 std::size_t idx2 = edge.v2Index; 92 auto v1 = vertices[idx1].position; 93 auto v2 = vertices[idx2].position; 94 DrawLineEx(v1, v2, EDGE_REDNER_SIZE, WHITE); 95 } 96 } 97 98 void Graph::traverseVertexIdx(std::size_t idx) { 99 this->vertices[idx].visited = true; 100 } 101 102 std::vector<Edge> Graph::getEdgesOfVertexIdx(std::size_t idx) { 103 return this->edges[idx]; 104 } 105 106 void Graph::setEdgeTraversed(Edge e) { 107 108 std::size_t source = e.v1Index; 109 std::size_t destination = e.v2Index; 110 111 if(source == destination) { 112 return; 113 } 114 115 auto& cEdges = edges[source]; 116 117 for(auto& edge : cEdges) { 118 if(edge.v2Index == destination || edge.v1Index == destination) { 119 edge.traversed = true; 120 } 121 } 122 123 auto& oEdges = edges[destination]; 124 125 for(auto& edge : oEdges) { 126 if(edge.v2Index == source || edge.v1Index == source) { 127 edge.traversed = true; 128 } 129 } 130 131 } 132 133 Vertex Graph::getVertex(std::size_t idx) { 134 // idx can't be negative bc size_t 135 if(idx >= vertices.size()) { 136 throw std::invalid_argument("idx out of bounds for vertex list"); 137 } 138 return vertices[idx]; 139 } 140 141 142 std::size_t Graph::getVertexCount() const noexcept { 143 return vertices.size(); 144 }