treewars/graph.cpp

168 lines
3.5 KiB
C++

#include "graph.h"
#include "mathutils.h"
#include "debug.h"
#include <list>
#include <algorithm>
#include <cassert>
using std::list;
Graph::Graph(bool planar)
{
this->planar = planar;
}
Graph::~Graph()
{
for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++)
{
Vertex* v = *cursor;
delete v;
}
}
bool Graph::point_in_vertex(int x, int y)
{
for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++)
{
Vertex* v = *cursor;
if (MathUtils::distance(v->x, v->y, x, y) <= v->r) return true;
}
return false;
}
Vertex * Graph::vertex_at(int x, int y)
{
for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++)
{
Vertex* v = *cursor;
if (MathUtils::distance(v->x, v->y, x, y) <= v->r) return v;
}
return NULL;
}
bool Graph::vertex_would_overlap(int x, int y, int r)
{
for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++)
{
Vertex* v = *cursor;
if (MathUtils::distance(v->x, v->y, x, y) <= v->r + r) return true;
}
return false;
}
bool Graph::crosses_edge(Vertex* a, Vertex* b)
{
for (list<Vertex*>::iterator cursor = vertices.begin();
cursor != vertices.end(); cursor++)
{
Vertex* v = *cursor;
for (list<Vertex*>::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(int x, int y, int r, int colour, int score, Vertex* src)
{
Vertex* v = new Vertex(x, y, r, colour, score);
// Make sure the nodes won't overlap
if (vertex_would_overlap(v->x, v->y, v->r))
{
#ifdef DEBUG
fprintf(stderr, "debug: Graph::add_vertex(): failed to add due to vertex collision: x=%d, y=%d, r=%d\n", v->x, v->y, v->r);
#endif
delete v;
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
delete v;
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, r=%d, score=%d\n", v->x, v->y, v->r, v->score);
#endif
return true;
}
list<Vertex*> Graph::get_colour(int colour)
{
list<Vertex*> answer;
for (list<Vertex*>::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<Vertex*>::iterator cursor;
for (cursor = target->neighbors.begin(); cursor != target->neighbors.end();
cursor++)
{
list<Vertex*>::iterator subcursor = find(target->neighbors.begin(),
target->neighbors.end(),
*cursor);
assert(subcursor != target->neighbors.end());
target->neighbors.erase(subcursor);
}
cursor = find(vertices.begin(), vertices.end(), target);
assert(cursor != vertices.end());
vertices.erase(cursor);
delete target;
}
Vertex::Vertex(int x, int y, int r, int colour, int score)
{
this->x = x;
this->y = y;
this->r = r;
this->colour = colour;
this->score = score;
}