// //======================================================================= // Copyright (c) 2004 Kristopher Beevers // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= // #include #include #include #include #include //#include #include #include #include #include #include // for sqrt // auxiliary types struct location { float y, x; // lat, long }; typedef float cost; template class city_writer { public: city_writer(Name n, LocMap l, float _minx, float _maxx, float _miny, float _maxy, unsigned int _ptx, unsigned int _pty) : name(n), loc(l), minx(_minx), maxx(_maxx), miny(_miny), maxy(_maxy), ptx(_ptx), pty(_pty) {} template void operator()(std::ostream& out, const Vertex& v) const { float px = 1 - (loc[v].x - minx) / (maxx - minx); float py = (loc[v].y - miny) / (maxy - miny); out << "[label=\"" << name[v] << "\", pos=\"" << static_cast(ptx * px) << "," << static_cast(pty * py) << "\", fontsize=\"11\"]"; } private: Name name; LocMap loc; float minx, maxx, miny, maxy; unsigned int ptx, pty; }; template class time_writer { public: time_writer(WeightMap w) : wm(w) {} template void operator()(std::ostream &out, const Edge& e) const { out << "[label=\"" << wm[e] << "\", fontsize=\"11\"]"; } private: WeightMap wm; }; // euclidean distance heuristic template class distance_heuristic : public boost::astar_heuristic { public: typedef typename boost::graph_traits::vertex_descriptor Vertex; distance_heuristic(LocMap l, Vertex goal) : m_location(l), m_goal(goal) {} CostType operator()(Vertex u) { CostType dx = m_location[m_goal].x - m_location[u].x; CostType dy = m_location[m_goal].y - m_location[u].y; return ::sqrt(dx * dx + dy * dy); } private: LocMap m_location; Vertex m_goal; }; struct found_goal {}; // exception for termination // visitor that terminates when we find the goal template class astar_goal_visitor : public boost::default_astar_visitor { public: astar_goal_visitor(Vertex goal) : m_goal(goal) {} template void examine_vertex(Vertex u, Graph& g) { if(u == m_goal) throw found_goal(); } private: Vertex m_goal; }; struct EdgePropertyMap { cost weight; }; int main(int argc, char **argv) { typedef boost::adjacency_list mygraph_t; typedef mygraph_t::vertex_descriptor vertex; typedef mygraph_t::edge_descriptor edge_descriptor; typedef mygraph_t::vertex_iterator vertex_iterator; typedef std::pair edge; // specify data enum nodes { Troy=0, LakePlacid, Plattsburgh, Massena, Watertown, Utica, Syracuse, Rochester, Buffalo, Ithaca, Binghamton, Woodstock, NewYork, N }; const char *name[] = { "Troy", "Lake Placid", "Plattsburgh", "Massena", "Watertown", "Utica", "Syracuse", "Rochester", "Buffalo", "Ithaca", "Binghamton", "Woodstock", "New York" }; location locations[] = { // lat/long {42.73, 73.68}, {44.28, 73.99}, {44.70, 73.46}, {44.93, 74.89}, {43.97, 75.91}, {43.10, 75.23}, {43.04, 76.14}, {43.17, 77.61}, {42.89, 78.86}, {42.44, 76.50}, {42.10, 75.91}, {42.04, 74.11}, {40.67, 73.94} }; edge edge_array[] = { edge(Troy,Utica), edge(Troy,LakePlacid), edge(Troy,Plattsburgh), edge(LakePlacid,Plattsburgh), edge(Plattsburgh,Massena), edge(LakePlacid,Massena), edge(Massena,Watertown), edge(Watertown,Utica), edge(Watertown,Syracuse), edge(Utica,Syracuse), edge(Syracuse,Rochester), edge(Rochester,Buffalo), edge(Syracuse,Ithaca), edge(Ithaca,Binghamton), edge(Ithaca,Rochester), edge(Binghamton,Troy), edge(Binghamton,Woodstock), edge(Binghamton,NewYork), edge(Syracuse,Binghamton), edge(Woodstock,Troy), edge(Woodstock,NewYork) }; unsigned int num_edges = sizeof(edge_array) / sizeof(edge); cost weights[] = { // estimated travel time (mins) 96, 134, 143, 65, 115, 133, 117, 116, 74, 56, 84, 73, 69, 70, 116, 147, 173, 183, 74, 71, 124 }; // create graph mygraph_t g(N); //typedef boost::property_map::type WeightMap; //WeightMap weightmap = get(boost::edge_weight, g); typedef boost::property_map::type WeightMap; WeightMap weightmap = boost::get(&EdgePropertyMap::weight, g); for(std::size_t j = 0; j < num_edges; ++j) { edge_descriptor e; bool inserted; boost::tie(e, inserted) = boost::add_edge(edge_array[j].first, edge_array[j].second, g); weightmap[e] = weights[j]; } // pick random start/goal boost::mt19937 gen(std::time(0)); vertex start = boost::random_vertex(g, gen); vertex goal = boost::random_vertex(g, gen); std::cout << "Start vertex: " << name[start] << std::endl; std::cout << "Goal vertex: " << name[goal] << std::endl; std::vector p(boost::num_vertices(g)); std::vector d(boost::num_vertices(g)); try { boost::astar_search (g, start, distance_heuristic(locations, goal), boost::visitor(astar_goal_visitor(goal)). // Only the first of named parameters needs boost:: predecessor_map(&p[0]).distance_map(&d[0]) );//. } catch(found_goal fg) { // found a path to the goal std::list shortest_path; for(vertex v = goal;; v = p[v]) { shortest_path.push_front(v); if(p[v] == v) break; } std::cout << "Shortest path from " << name[start] << " to " << name[goal] << ": "; std::list::iterator spi = shortest_path.begin(); std::cout << name[start]; for(++spi; spi != shortest_path.end(); ++spi) std::cout << " -> " << name[*spi]; std::cout << std::endl << "Total travel time: " << d[goal] << std::endl; return 0; } std::cout << "Didn't find a path from " << name[start] << " to " << name[goal] << "!" << std::endl; return 0; }