visualizations

Programmatic visualizations
git clone git://git.laack.co/visualizations.git
Log | Files | Refs | README

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 }