#include "graph.h" #include "mathutils.h" #include "debug.h" #include #include #include using std::list; Graph::Graph(bool planar) { this->planar = planar; } Graph::~Graph() { for (list::iterator cursor = vertices.begin(); cursor != vertices.end(); cursor++) { Vertex* v = *cursor; delete v; } } // In 3-space, this will be less useful, because we'll be clicking on the // objects themselves... but we'll cross that bridge when we get there bool Graph::point_in_vertex(int x, int y, int z) { for (list::iterator cursor = vertices.begin(); cursor != vertices.end(); cursor++) { Vertex* v = *cursor; if (MathUtils::distance(v->x, v->y, v->z, x, y, z) <= v->r) return true; } return false; } Vertex * Graph::vertex_at(int x, int y, int z) { for (list::iterator cursor = vertices.begin(); cursor != vertices.end(); cursor++) { Vertex* v = *cursor; if (MathUtils::distance(v->x, v->y, v->z, x, y, z) <= v->r) return v; } return NULL; } bool Graph::vertex_would_overlap(int x, int y, int z, int r) { for (list::iterator cursor = vertices.begin(); cursor != vertices.end(); cursor++) { Vertex* v = *cursor; if (MathUtils::distance(v->x, v->y, v->z, x, y, z) <= v->r + r) return true; } return false; } bool Graph::crosses_edge(Vertex* a, Vertex* b) { for (list::iterator cursor = vertices.begin(); cursor != vertices.end(); cursor++) { Vertex* v = *cursor; for (list::iterator subcursor = v->neighbors.begin(); subcursor != v->neighbors.end(); subcursor++) { Vertex* w = *subcursor; if (MathUtils::lines_intersect(a->x, a->y, b->x, b->y, v->x, v->y, w->x, w->y)) return true; } } return false; } bool Graph::add_vertex(Vertex* v, Vertex* src) { // Make sure the nodes won't overlap if (vertex_would_overlap(v->x, v->y, v->z, v->r)) { #ifdef DEBUG fprintf(stderr, "debug: Graph::add_vertex(): failed to add due to vertex collision: x=%d, y=%d, z=%d, r=%d\n", v->x, v->y, v->z, v->r); #endif return false; } if (src != NULL) { if (planar && crosses_edge(v, src)) { #ifdef DEBUG fprintf(stderr, "debug: Graph::add_vertex(): failed to add due to edge collision: x1=%d, y1=%d, x2=%d, y2=%d\n", v->x, v->y, src->x, src->y); #endif return false; } v->neighbors.push_back(src); src->neighbors.push_back(v); } vertices.push_back(v); #ifdef DEBUG fprintf(stderr, "debug: Graph::add_vertex(): added: x=%d, y=%d, z=%d, r=%d, score=%d, colour=%x\n", v->x, v->y, v->z, v->r, v->score, v->colour); #endif return true; } list Graph::get_colour(int colour) { list answer; for (list::iterator cursor = vertices.begin(); cursor != vertices.end(); cursor++) { Vertex* v = *cursor; if (v->colour == colour) answer.push_back(v); } return answer; } void Graph::remove_vertex(Vertex* target) { list::iterator cursor; for (cursor = target->neighbors.begin(); cursor != target->neighbors.end(); cursor++) { list::iterator subcursor = find((*cursor)->neighbors.begin(), (*cursor)->neighbors.end(), target); assert(subcursor != (*cursor)->neighbors.end()); (*cursor)->neighbors.erase(subcursor); } cursor = find(vertices.begin(), vertices.end(), target); assert(cursor != vertices.end()); vertices.erase(cursor); delete target; }