mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 17:51:28 +00:00
759 lines
19 KiB
C++
759 lines
19 KiB
C++
/*
|
|
|
|
Fear Pathing generation utility.
|
|
(c) 2005 Father Nitwit
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "../common/types.h"
|
|
#include "../zone/map.h"
|
|
#include "../common/rdtsc.h"
|
|
#include "quadtree.h"
|
|
#include "apathing.h"
|
|
#include "boostcrap.h"
|
|
#include <stdio.h>
|
|
#include <mysql.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <gd.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
We assume this overwrites the edge array in big
|
|
and does not free the old edges
|
|
*/
|
|
void build_boost_graph(MyGraph &vg, property_map<MyGraph, edge_weight_t>::type &weightmap, map<PathEdge *, EdgeDesc> &em, PathGraph *big, bool set_weights) {
|
|
|
|
list<PathEdge*>::iterator cur,end;
|
|
list<PathNode*>::iterator curn,endn;
|
|
PathNode *n;
|
|
PathEdge *e;
|
|
|
|
//first we need to number our nodes...
|
|
curn = big->nodes.begin();
|
|
endn = big->nodes.end();
|
|
int r = 0;
|
|
for(; curn != endn; curn++) {
|
|
n = *curn;
|
|
n->node_id = r;
|
|
r++;
|
|
}
|
|
|
|
typedef std::pair < int, int > E; //our edge type
|
|
|
|
weightmap = get(edge_weight, vg);
|
|
|
|
//now add all our edges to the graph
|
|
cur = big->edges.begin();
|
|
end = big->edges.end();
|
|
for(r = 0; cur != end; cur++, r++) {
|
|
e = *cur;
|
|
if(e->from == e->to)
|
|
continue;
|
|
|
|
// printf("A %d/%d (%.3f,%.3f,%.3f) -> (%.3f,%.3f,%.3f) d=%.3f\n", r, big->edges.size(), e->from->x, e->from->y, e->from->z, e->to->x, e->to->y, e->to->z, e->from->Dist2(e->to));
|
|
EdgeDesc ed;
|
|
bool inserted;
|
|
tie(ed, inserted) = add_edge(e->from->node_id, e->to->node_id, vg);
|
|
if(set_weights)
|
|
weightmap[ed] = int(e->from->Dist2(e->to));
|
|
else
|
|
weightmap[ed] = 1;
|
|
em[e] = ed;
|
|
// e->edge_id = ed;
|
|
}
|
|
//now we should have a nice happy undirected graph...
|
|
}
|
|
|
|
void run_min_spanning_tree(MyGraph &vg, property_map<MyGraph, edge_weight_t>::type &weightmap, map<PathEdge *, EdgeDesc> &em, PathGraph *big, int start_node) {
|
|
int noedge = 0;
|
|
list<PathEdge *> out_paths;
|
|
|
|
vector < EdgeDesc > spanning_tree;
|
|
|
|
kruskal_minimum_spanning_tree(vg, back_inserter(spanning_tree));
|
|
|
|
vector < EdgeDesc >::iterator cur,end;
|
|
list<PathEdge*>::iterator cure,ende;
|
|
cur = spanning_tree.begin();
|
|
end = spanning_tree.end();
|
|
for(; cur != end; cur++) {
|
|
//find the edge
|
|
cure = big->edges.begin();
|
|
ende = big->edges.end();
|
|
for(; cure != ende; cure++) {
|
|
if(em[*cure] == *cur) {
|
|
out_paths.push_back(new PathEdge((*cure)->from, (*cure)->to));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
noedge = big->edges.size() - out_paths.size() - 1;
|
|
printf("Ran Min Spanning Tree: %d paths were eliminated.\n", noedge);
|
|
|
|
|
|
/*
|
|
//make our results list.
|
|
vector < VertDesc > p(num_vertices(vg));
|
|
|
|
//finally run the stupid algorithm.
|
|
prim_minimum_spanning_tree(vg, &p[0], root_vertex(start_node));
|
|
|
|
|
|
for (std::size_t i = 0; i != p.size(); ++i) {
|
|
if (p[i] != i) {
|
|
out_paths.push_back(new PathEdge(big->nodes[p[i]], big->nodes[i]));
|
|
} else {
|
|
//no edge here...
|
|
noedge++;
|
|
}
|
|
}
|
|
printf("Ran Min Spanning Tree: %d nodes were disconnected.\n", noedge);
|
|
|
|
|
|
*/
|
|
|
|
//now swap out our edge list to the MST.
|
|
big->edges = out_paths;
|
|
}
|
|
|
|
void find_disjoint_grids(Map *map, MyGraph &vg, PathGraph *big, const char *fname, vector<int> &start_nodes, vector<PathGraph *> &disjoints) {
|
|
|
|
vector< vector<int> > D;
|
|
vector<int> counts;
|
|
vector<int> disjoint_counts;
|
|
vector<int> first_node;
|
|
|
|
//color the graph and get us the info we need to do out job
|
|
color_disjoint_graphs(big, vg, map, fname, D, counts, disjoint_counts, first_node);
|
|
|
|
|
|
//find the biggest grid, that one gets to be included no matter what
|
|
int best_graph = 0;
|
|
int best_count = counts[0];
|
|
unsigned int r;
|
|
for(r = 1; r < counts.size(); r++) {
|
|
if(best_count < counts[r]) {
|
|
best_count = counts[r];
|
|
best_graph = r;
|
|
}
|
|
}
|
|
disjoint_counts[best_graph] = 1;
|
|
|
|
|
|
//break up the graphs based on color if we want them.
|
|
vector<int>::iterator ccur,djcur,fcur,cend;
|
|
list<PathEdge*>::iterator cur,end;
|
|
PathEdge *e;
|
|
PathGraph *pg;
|
|
ccur = counts.begin();
|
|
djcur = disjoint_counts.begin();
|
|
fcur = first_node.begin();
|
|
cend = counts.end();
|
|
int color = 0;
|
|
for(; ccur != cend; ccur++, djcur++, fcur++, color++) {
|
|
int count = *ccur;
|
|
int dj = *djcur;
|
|
// int fn = *fcur;
|
|
|
|
if(dj < 1)
|
|
continue; //skip disjoint sets not marked for use.
|
|
|
|
if(count < MIN_DISJOINT_NODES)
|
|
continue; //make sure we have a reasonable node count
|
|
|
|
pg = new PathGraph();
|
|
|
|
cur = big->edges.begin();
|
|
end = big->edges.end();
|
|
for(; cur != end; cur++) {
|
|
e = *cur;
|
|
if(e->from->color != e->to->color) {
|
|
printf("Color Mismatch %d-%d: #%d(%.3f,%.3f,%.3f) -> #%d(%.3f,%.3f,%.3f)\n", e->from->color, e->to->color, e->from->node_id, e->from->x, e->from->y, e->from->z, e->to->node_id, e->to->x, e->to->y, e->to->z);
|
|
//... what to do...
|
|
}
|
|
//just use the color of the from node
|
|
if(e->from->color == color) {
|
|
pg->edges.push_back(e);
|
|
}
|
|
}
|
|
|
|
//get our list of nodes based on our edge list.
|
|
rebuild_node_list(pg->edges, pg->nodes, NULL);
|
|
|
|
disjoints.push_back(pg);
|
|
start_nodes.push_back(1); //each graph only contains its own nodes, so any node will work.
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
int best_graph = 0;
|
|
int best_count = counts[0];
|
|
unsigned int r;
|
|
for(r = 1; r < counts.size(); r++) {
|
|
if(best_count < counts[r]) {
|
|
best_count = counts[r];
|
|
best_graph = r;
|
|
}
|
|
// printf("Graph %d has %d edges\n", r, counts[r]);
|
|
}
|
|
|
|
start_node = first_node[best_graph];
|
|
printf("Best sub-graph: chose #%d of %d, has %d nodes, and contains node %d\n", best_graph, counts.size()-1, best_count, start_node);
|
|
//todo: eliminate other graphs...
|
|
*/
|
|
|
|
/* list<PathEdge*>::iterator cure,ende;
|
|
PathEdge *e;
|
|
cure = big->edges.begin();
|
|
ende = big->edges.end();
|
|
for(; cure != ende; cure++) {
|
|
e = *cure;
|
|
if(e->from->color != e->to->color) {
|
|
printf("Color Mismatch %d-%d: #%d(%.3f,%.3f,%.3f) -> #%d(%.3f,%.3f,%.3f)\n", e->from->color, e->to->color, e->from->node_id, e->from->x, e->from->y, e->from->z, e->to->node_id, e->to->x, e->to->y, e->to->z);
|
|
} else if(e->from->color != best_graph) {
|
|
printf("Color %d: (%.3f,%.3f,%.3f) -> (%.3f,%.3f,%.3f)\n", e->from->color, e->from->x, e->from->y, e->from->z, e->to->x, e->to->y, e->to->z);
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
|
|
static const int INT_LIMIT = (std::numeric_limits < int >::max)();
|
|
|
|
void color_disjoint_graphs(
|
|
PathGraph *big,
|
|
MyGraph &vg,
|
|
Map *map,
|
|
const char *fname,
|
|
|
|
vector< vector<int> > &D, //output
|
|
vector<int> &counts, //output
|
|
vector<int> &disjoint_counts, //output
|
|
vector<int> &first_node //output
|
|
) {
|
|
|
|
|
|
int count = big->nodes.size();
|
|
// int r;
|
|
|
|
// vector< vector<int> > D(count, vector<int>(count, INT_LIMIT));
|
|
// vector<int> counts(1, 0);
|
|
// vector<int> first_node(1, 0);
|
|
|
|
//make sure everything is inited right...
|
|
D.resize(0);
|
|
D.resize(count, vector<int>(count, INT_LIMIT));
|
|
counts.resize(1);
|
|
counts[0] = 0;
|
|
disjoint_counts.resize(1);
|
|
disjoint_counts[0] = 0;
|
|
first_node.resize(1);
|
|
first_node[0] = 0;
|
|
|
|
//make up a weight map with all 1s, done while building now
|
|
/* property_map < MyGraph, edge_weight_t >::type w = get(edge_weight, vg);
|
|
graph_traits < MyGraph >::edge_iterator e, e_end;
|
|
for (boost::tie(e, e_end) = edges(vg); e != e_end; ++e)
|
|
w[*e] = 1;*/
|
|
|
|
|
|
johnson_all_pairs_shortest_paths(vg, D);
|
|
|
|
list<PathNode*>::iterator cur,end,cur2;
|
|
PathNode *n,*f;
|
|
|
|
int cur_color = 1;
|
|
int cc,djc;
|
|
|
|
//clear node colors
|
|
cur = big->nodes.begin();
|
|
end = big->nodes.end();
|
|
for(; cur != end; cur++) {
|
|
n = *cur;
|
|
n->color = 0;
|
|
}
|
|
|
|
|
|
//color the graph based on reachability, basically labeling subgraphs
|
|
//this finds the number of nodes reachable from each node
|
|
//which is used to pick the best disconnected graph in the tree.
|
|
//its a series of wrong bullshit that forces us to do this, but it works
|
|
cur = big->nodes.begin();
|
|
end = big->nodes.end();
|
|
for(; cur != end; cur++) {
|
|
n = *cur;
|
|
if(n->color != 0)
|
|
continue; //allready visited
|
|
|
|
|
|
cc = 1;
|
|
djc = 0;
|
|
|
|
if(n->disjoint)
|
|
djc++;
|
|
|
|
n->color = cur_color;
|
|
cur_color++;
|
|
|
|
cur2 = cur;
|
|
for(; cur2 != end; cur2++) {
|
|
f = *cur2;
|
|
if(f->color == 0 && D[n->node_id][f->node_id] != INT_LIMIT) {
|
|
cc++;
|
|
f->color = n->color;
|
|
}
|
|
if(f->disjoint)
|
|
djc++;
|
|
}
|
|
counts.push_back(cc);
|
|
disjoint_counts.push_back(djc);
|
|
first_node.push_back(n->node_id);
|
|
}
|
|
|
|
#ifdef DRAW_ALL_COLORS
|
|
|
|
if(fname != NULL) {
|
|
printf("Drawing with %d seperate sub-graphs from %d nodes and %d edges\n", cur_color-1, big->nodes.size(), big->edges.size());
|
|
|
|
FILE *pngout;
|
|
pngout = fopen(fname, "wb");
|
|
if(pngout == NULL) {
|
|
printf("Unable to open %s\n", fname);
|
|
return;
|
|
}
|
|
|
|
gdImagePtr im;
|
|
int minx = int(map->GetMinX());
|
|
int maxx = int(map->GetMaxX());
|
|
int miny = int(map->GetMinY());
|
|
int maxy = int(map->GetMaxY());
|
|
|
|
im = gdImageCreate((maxx - minx)/IMAGE_SCALE, (maxy - miny)/IMAGE_SCALE);
|
|
// im = gdImageCreate(maxx - minx, maxy - miny);
|
|
|
|
//allocate this first, to make it the BG color.
|
|
/*int black =*/ gdImageColorAllocate(im, 0, 0, 0);
|
|
|
|
// int grey = gdImageColorAllocate(im, 100, 100, 100);
|
|
|
|
int *clist = new int[cur_color];
|
|
int r;
|
|
for(r = 0; r < cur_color; r++) {
|
|
clist[r] = gdImageColorAllocate(im, rand()%255, rand()%255, rand()%255);
|
|
}
|
|
|
|
{
|
|
list<PathEdge*>::iterator cur,end;
|
|
PathEdge *e;
|
|
|
|
cur = big->edges.begin();
|
|
end = big->edges.end();
|
|
for(; cur != end; cur++) {
|
|
e = *cur;
|
|
int x1 = int(e->from->x) - minx;
|
|
int y1 = int(e->from->y) - miny;
|
|
int x2 = int(e->to->x) - minx;
|
|
int y2 = int(e->to->y) - miny;
|
|
x1 /= IMAGE_SCALE;
|
|
y1 /= IMAGE_SCALE;
|
|
x2 /= IMAGE_SCALE;
|
|
y2 /= IMAGE_SCALE;
|
|
gdImageLine(im, x1, y1, x2, y2, clist[e->from->color]);
|
|
}
|
|
}
|
|
delete[] clist;
|
|
|
|
gdImagePng(im, pngout);
|
|
gdImageDestroy(im);
|
|
|
|
fclose(pngout);
|
|
|
|
printf("Wrote image: %s\n", fname);
|
|
}
|
|
#endif //DRAW_ALL_COLORS
|
|
}
|
|
|
|
void calc_path_lengths(Map *map, MyGraph &vg, PathGraph *big, map<PathEdge *, EdgeDesc> &em, const char *fname) {
|
|
|
|
vector<int> counts;
|
|
vector<int> disjoint_counts;
|
|
vector<int> first_node;
|
|
vector< vector<int> > D;
|
|
list<PathNode*>::iterator cur,end;
|
|
PathNode *n;
|
|
|
|
/*
|
|
Node distances:
|
|
1. find the root node.
|
|
- find the longest path from each node to any other node
|
|
- the node with the shortest of these longest paths is the root
|
|
2. record each node's distance from that root node
|
|
*/
|
|
|
|
//color the graph and get us the info we need to do out job
|
|
color_disjoint_graphs(big, vg, map, fname, D, counts, disjoint_counts, first_node);
|
|
|
|
|
|
vector<int>::iterator curp,endp;
|
|
|
|
int shortest_node = 0;
|
|
int shortest = 0xFFFFFF;
|
|
int the_longest = 0;
|
|
int longest_node = 0;
|
|
|
|
//stores the longest path from each node
|
|
vector<int> longest_dists(D.size(), 0);
|
|
|
|
//find the node with the longest path of all, so we know what
|
|
//tree we are trying to find the root of
|
|
cur = big->nodes.begin();
|
|
end = big->nodes.end();
|
|
for(; cur != end; cur++) {
|
|
n = *cur;
|
|
vector<int> &cv = D[n->node_id];
|
|
curp = cv.begin();
|
|
endp = cv.end();
|
|
int longest = 0;
|
|
int discount = 0;
|
|
for(; curp != endp; curp++) {
|
|
if(*curp == INT_LIMIT) {
|
|
discount++;
|
|
continue;
|
|
}
|
|
if(*curp > longest)
|
|
longest = *curp;
|
|
}
|
|
|
|
longest_dists[n->node_id] = longest;
|
|
|
|
if(longest > the_longest) {
|
|
the_longest = longest;
|
|
longest_node = n->node_id;
|
|
}
|
|
}
|
|
|
|
//find the node with the shortest, longest path
|
|
//the idea is to locate the 'root' of the tree.
|
|
cur = big->nodes.begin();
|
|
end = big->nodes.end();
|
|
for(; cur != end; cur++) {
|
|
n = *cur;
|
|
vector<int> &cv = D[n->node_id];
|
|
if(cv[longest_node] == INT_LIMIT)
|
|
continue; //this node cannot reach the root
|
|
|
|
int longest = longest_dists[n->node_id];
|
|
//n->longest_path = longest;
|
|
//printf("Node %d's longest path is %d\n", n->node_id, longest);
|
|
|
|
if(longest < shortest) {
|
|
shortest = longest;
|
|
shortest_node = n->node_id;
|
|
}
|
|
}
|
|
|
|
//now we have our root, set each node to their distance from the root
|
|
vector<int> &root_dists = D[shortest_node];
|
|
printf("The tree's root is %d\n", shortest_node);
|
|
cur = big->nodes.begin();
|
|
end = big->nodes.end();
|
|
for(; cur != end; cur++) {
|
|
n = *cur;
|
|
if(n->node_id == shortest_node)
|
|
n->longest_path = 0;
|
|
else
|
|
n->longest_path = root_dists[n->node_id];
|
|
//printf("Node %d's distance from root is %d\n", n->node_id, root_dists[n->node_id]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
the reachability is the number of nodes which we could possibly get to
|
|
by traveling each direction across an edge.
|
|
|
|
to find reachability:
|
|
loop through each edge e
|
|
Remove that edge from the graph
|
|
color_disjoint_graphs
|
|
fc = count number of nodes with the same color as 'e->from'
|
|
tc = count number of nodes with the same color as 'e->to'
|
|
e->normal_reach = tc;
|
|
e->reverse_reach = fc;
|
|
*/
|
|
property_map<MyGraph, edge_weight_t>::type weightmap;
|
|
weightmap = get(edge_weight, vg);
|
|
|
|
int tc,fc;
|
|
int from_color, to_color;
|
|
|
|
printf("Finding lengths (%d dots)", 1+big->edges.size()/10);
|
|
int pos = 0;
|
|
|
|
PathEdge *e;
|
|
list<PathEdge*>::iterator cur4,end4;
|
|
cur4 = big->edges.begin();
|
|
end4 = big->edges.end();
|
|
for(; cur4 != end4; cur4++, pos++) {
|
|
if(pos % 10 == 0) {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
e = *cur4;
|
|
|
|
//remove this edge from the boost graph..
|
|
remove_edge(em[e], vg);
|
|
|
|
//color the graph and get us the info we need to do our job
|
|
//char out[64];
|
|
//sprintf(out, "lengraph-%d.png", pos);
|
|
color_disjoint_graphs(big, vg, map,
|
|
NULL,
|
|
D, counts, disjoint_counts, first_node);
|
|
|
|
//add the edge back in
|
|
EdgeDesc ed;
|
|
bool inserted;
|
|
tie(ed, inserted) = add_edge(e->from->node_id, e->to->node_id, vg);
|
|
em[e] = ed;
|
|
weightmap[em[e]] = int(e->from->Dist2(e->to)); //cause its a new edge
|
|
|
|
//make sure this stupid thing worked.
|
|
if(e->from->color == e->to->color) {
|
|
printf("Cycle detected in MST... WTF?\n");
|
|
e->normal_reach = -1;
|
|
e->reverse_reach = -1;
|
|
continue;
|
|
}
|
|
from_color = e->from->color;
|
|
to_color = e->to->color;
|
|
|
|
//count our crap.
|
|
tc = 0;
|
|
fc = 0;
|
|
cur = big->nodes.begin();
|
|
end = big->nodes.end();
|
|
for(; cur != end; cur++) {
|
|
n = *cur;
|
|
if(n->color == to_color)
|
|
tc++;
|
|
else if(n->color == from_color)
|
|
fc++;
|
|
}
|
|
|
|
//put it on our edge
|
|
e->normal_reach = tc;
|
|
e->reverse_reach = fc;
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
//re-color the graph, since we dicked with it above
|
|
color_disjoint_graphs(big, vg, map, fname, D, counts, disjoint_counts, first_node);
|
|
choose_biggest_graph(big, counts, first_node);
|
|
}
|
|
|
|
|
|
|
|
void just_color_the_damned_thing(Map *map, PathGraph *big, const char *fname) {
|
|
MyGraph vg(big->nodes.size());
|
|
property_map<MyGraph, edge_weight_t>::type weightlist_mst;
|
|
std::map<PathEdge *, EdgeDesc> edgemap_mst;
|
|
build_boost_graph(vg, weightlist_mst, edgemap_mst, big, true);
|
|
|
|
vector<int> counts;
|
|
vector<int> disjoint_counts;
|
|
vector<int> first_node;
|
|
vector< vector<int> > D;
|
|
list<PathNode*>::iterator cur,end;
|
|
|
|
color_disjoint_graphs(big, vg, map, fname, D, counts, disjoint_counts, first_node);
|
|
}
|
|
|
|
/*
|
|
void calc_path_lengths(Map *map, MyGraph &vg, PathGraph *big, vector< vector<int> > &D, const char *fname) {
|
|
|
|
// vector< vector<int> > D;
|
|
vector<int> counts;
|
|
vector<int> first_node;
|
|
|
|
|
|
choose_biggest_graph(big, counts, first_node);
|
|
}
|
|
*/
|
|
|
|
|
|
//assumes that the graph is freshly colored disjoint, and counts/first_node are results from it
|
|
void choose_biggest_graph(PathGraph *big, vector<int> &counts, vector<int> &first_node) {
|
|
int best_graph = 0;
|
|
int best_count = counts[0];
|
|
unsigned int r;
|
|
for(r = 1; r < counts.size(); r++) {
|
|
if(best_count < counts[r]) {
|
|
best_count = counts[r];
|
|
best_graph = r;
|
|
}
|
|
printf("Graph %d has %d edges\n", r, counts[r]);
|
|
}
|
|
|
|
printf("Best Tree: Detected %d graphs in the MST, selected #%d\n", counts.size(), best_graph);
|
|
|
|
list<PathNode*> new_nodes;
|
|
list<PathEdge*> new_edges;
|
|
|
|
//rebuild the node list to include only nodes which are in
|
|
//the best graph, also only keeping the edges which connect them.
|
|
std::map<PathNode *, int> havenodelist;
|
|
list<PathEdge*>::iterator cur4,end4;
|
|
cur4 = big->edges.begin();
|
|
end4 = big->edges.end();
|
|
for(; cur4 != end4; cur4++) {
|
|
PathEdge *e = *cur4;
|
|
|
|
//remove the edge if it is not the main color
|
|
//this also causes the removal of the nodes if they
|
|
//are not used in any other edges.
|
|
if(e->from->color != e->to->color) {
|
|
printf("Miscolor.\n");
|
|
continue;
|
|
}
|
|
if(e->from->color != best_graph) {
|
|
continue;
|
|
}
|
|
if(e->to->color != best_graph) {
|
|
continue;
|
|
}
|
|
|
|
new_edges.push_back(e);
|
|
|
|
if(havenodelist.count(e->from) != 1) {
|
|
e->from->final_id = new_nodes.size();
|
|
new_nodes.push_back(e->from);
|
|
havenodelist[e->from] = 1;
|
|
}
|
|
if(havenodelist.count(e->to) != 1) {
|
|
e->to->final_id = new_nodes.size();
|
|
new_nodes.push_back(e->to);
|
|
havenodelist[e->to] = 1;
|
|
}
|
|
}
|
|
|
|
printf("Best Tree: Removed %d nodes and %d edges which were disconnected.\n",
|
|
big->nodes.size() - new_nodes.size(), big->edges.size() - new_edges.size());
|
|
big->nodes = new_nodes;
|
|
big->edges = new_edges;
|
|
}
|
|
|
|
void consolidate_cross_graphs(Map *map, PathGraph *big, PathGraph *excess, MyGraph &cross_graph, const char *fname) {
|
|
|
|
vector< vector<int> > D;
|
|
vector<int> counts;
|
|
vector<int> disjoint_counts;
|
|
vector<int> first_node;
|
|
|
|
//color the graph and get us the info we need to do our job
|
|
color_disjoint_graphs(big, cross_graph, map, fname, D, counts, disjoint_counts, first_node);
|
|
}
|
|
|
|
void find_path_info(Map *map, MyGraph &vg, vector< vector<PathEdge*> > &path_finding, PathGraph *big) {
|
|
//make sure our path finding vector is big enough.
|
|
{
|
|
int size = big->nodes.size();
|
|
vector<PathEdge*> tmp(size, (PathEdge*)NULL);
|
|
path_finding.resize(0);
|
|
path_finding.resize(size, tmp);
|
|
}
|
|
|
|
vector< vector<int> > D;
|
|
vector<int> counts;
|
|
vector<int> disjoint_counts;
|
|
vector<int> first_node;
|
|
|
|
//color the graph and get us the info we need to do our job
|
|
color_disjoint_graphs(big, vg, map, NULL, D, counts, disjoint_counts, first_node);
|
|
|
|
//figure out what edges link to each node.
|
|
std::map<PathNode*, vector<PathEdge*> > node_edges;
|
|
find_node_edges(big, node_edges);
|
|
|
|
|
|
//for each node, find best edge to reach each other node.
|
|
list<PathNode*>::iterator cur,end;
|
|
PathNode *n;
|
|
vector<int>::iterator curp,endp;
|
|
vector<PathEdge *>::iterator cure,ende;
|
|
int r;
|
|
cur = big->nodes.begin();
|
|
end = big->nodes.end();
|
|
for(; cur != end; cur++) {
|
|
n = *cur;
|
|
//get all our vector refs that we need since this is kinda expensive
|
|
vector<int> &cv = D[n->node_id]; //distance array
|
|
vector<PathEdge *> &pf = path_finding[n->node_id]; //result
|
|
vector<PathEdge *> &el = node_edges[n]; //our edges
|
|
curp = cv.begin();
|
|
endp = cv.end();
|
|
for(r = 0; curp != endp; curp++, r++) {
|
|
if(n->node_id == r) {
|
|
//this is the end of the path, we cannot take an edge to reach ourself
|
|
pf[r] = NULL;
|
|
continue;
|
|
}
|
|
int my_dist = *curp;
|
|
if(my_dist == INT_MAX) {
|
|
//this node is unreachable.
|
|
pf[r] = NULL;
|
|
continue;
|
|
}
|
|
|
|
//else, node r reachable from us, find best edge.
|
|
cure = el.begin();
|
|
ende = el.end();
|
|
// int shortest;
|
|
PathEdge *ce;
|
|
PathNode *cn;
|
|
//for each edge
|
|
for(; cure != ende; cure++) {
|
|
ce = *cure;
|
|
//find the node other than ourself on the edge
|
|
if(ce->from == n)
|
|
cn = ce->to;
|
|
else
|
|
cn = ce->from;
|
|
//see how far away this node is
|
|
int cdist = D[cn->node_id][r];
|
|
if(cdist < my_dist) {
|
|
//found one which is closer... due to min span tree, there
|
|
//should only be one path possible so just go with it.
|
|
pf[r] = ce;
|
|
break;
|
|
}
|
|
}
|
|
//assume that this node got assigned.. next
|
|
if(pf[r] == NULL) {
|
|
printf("Node id %d was not able to find a good path to node %d\n", n->node_id, r);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|