pgRouting

root/tags/release-1.0-beta/shooting_star_boost_wrapper.cpp

Revision 39, 9.3 kB (checked in by anton, 1 year ago)

1.0.0b tag added

Line 
1 /*
2  * Shooting* Shortest path algorithm for PostgreSQL
3  *
4  * Copyright (c) 2007 Anton A. Patrushev, Orkney, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  */
21
22 #include <boost/config.hpp>
23 #include <iostream>
24 #include <fstream>
25
26 #include <boost/graph/graph_traits.hpp>
27 #include <boost/graph/adjacency_list.hpp>
28 #include <boost/vector_property_map.hpp>
29 #include <shooting_star_search.hpp>
30
31 #include "shooting_star.h"
32
33 #include <math.h>    // for sqrt
34
35 using namespace std;
36 using namespace boost;
37
38 // Maximal number of nodes in the path (to avoid infinite loops)
39 #define MAX_NODES 1000000
40
41 struct Edge
42 {
43   int id;
44   int source;
45   int target;
46   float8 cost;
47   float8 distance;
48   float8 rank;
49   std::map< int, std::pair<float8, std::vector<int> >, std::less<int> > adjacent_edges;
50
51   std::vector< int > history;
52
53   default_color_type color;
54  
55   std::size_t index;
56
57   adjacency_list_traits<vecS, vecS, directedS>::edge_descriptor predecessor;
58 };
59        
60 struct Vertex
61 {
62   int id;
63   float8 x;
64   float8 y;
65
66   default_color_type color;
67  
68   float8 cost;
69  
70 };
71
72
73 struct found_goal {}; // exception for termination
74
75 // visitor that terminates when we find the goal
76 template <class Edge>
77 class shooting_star_goal_visitor : public boost::default_shooting_star_visitor
78 {
79 public:
80   shooting_star_goal_visitor(Edge goal) : m_goal(goal) {}
81
82   template <class Graph>
83   void examine_edge(Edge e, Graph& g) {
84     if(g[e].id == g[m_goal].id)
85       throw found_goal();
86   }
87   template <class Graph>
88   void finish_edge(Edge e, Graph& g) {}
89 private:
90   Edge m_goal;
91 };
92
93
94 template <class Graph, class CostType>
95 class distance_heuristic : public astar_heuristic<Graph, CostType>
96 {
97 public:
98   typedef typename graph_traits<Graph>::edge_descriptor Edge;
99   distance_heuristic(Graph& g, Edge goal):m_g(g), m_goal(goal){}
100   CostType operator()(Edge e)
101   {
102     CostType dx = m_g[target(m_goal, m_g)].x - m_g[target(e, m_g)].x;
103     CostType dy = m_g[target(m_goal, m_g)].y - m_g[target(e, m_g)].y;
104     //You can choose any heuristical function from below
105     //return ::max(dx, dy);
106     //return ::sqrt(dx * dx + dy * dy)/2;
107     //return 0;
108     return (::fabs(dx)+::fabs(dy))/2;
109   }
110 private:
111   Graph& m_g;
112   Edge m_goal;
113 };
114
115
116 template <class G, class E>
117 static void
118 graph_add_edge(G &graph, int id, int source, int target,
119                float8 cost, float8 s_x, float8 s_y, float8 t_x, float8 t_y,
120                std::map< int, std::pair<float8, vector<int> >, std::less<int> > adjacent_edges)
121 {
122
123   E e;
124   bool inserted;
125
126   if (cost < 0) // edges are not inserted in the graph if cost is negative
127     return;
128
129   tie(e, inserted) = add_edge(source, target, graph);
130
131   graph[e].cost = cost;
132   graph[e].id = id;
133
134 //  put(edge_index, graph, graph[e], id);
135  
136   graph[e].source = source;
137   graph[e].target = target;
138  
139   graph[e].adjacent_edges = adjacent_edges;
140  
141   typedef typename graph_traits<G>::vertex_descriptor Vertex;
142   Vertex s = vertex(source, graph);
143   Vertex t = vertex(target, graph);
144
145   graph[s].id=source;
146   graph[t].id=target;
147
148   graph[s].x=s_x;
149   graph[s].y=s_y;
150   graph[t].x=t_x;
151   graph[t].y=t_y;
152
153 }
154
155 int
156 boost_shooting_star(edge_shooting_star_t *edges_array, unsigned int count,
157             int source_edge_id, int target_edge_id,
158             bool directed, bool has_reverse_cost,
159             path_element_t **path, int *path_count, char **err_msg, int e_max_id)
160 {
161
162   typedef adjacency_list<vecS, vecS, directedS, Vertex, Edge> graph_t;
163  
164   typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
165   typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
166
167   const unsigned int num_nodes = /*1*/count*2;
168  
169   int z;
170   int src, trg, offset;
171  
172   graph_t graph(num_nodes);
173
174   std::map< int, std::pair<float8, vector<int> >, std::less<int> > adjacent_edges;
175
176   std::map< int, int, std::less<int> > vertices;
177
178   offset = 0;
179  
180   for (std::size_t j = 0; j < count; ++j)
181   {
182     //Vertex ids renumbering moved here
183    
184     src = edges_array[j].source;
185     trg = edges_array[j].target;
186
187     if(vertices[src]==NULL)
188     //if (vertices.find(edges_array[j].source) == vertices.end())
189     {
190       vertices[src]=j+offset;
191       edges_array[j].source=j+offset;
192      
193     }
194     else
195     {
196       edges_array[j].source=vertices[src];
197     }
198
199     if(vertices[trg]==NULL)
200     //if (vertices.find(edges_array[j].target) == vertices.end())   
201     {
202       offset++;
203  
204       vertices[trg]=j+offset;
205       edges_array[j].target=j+offset;
206     }
207     else
208     {
209       edges_array[j].target=vertices[trg];
210     }
211    
212     adjacent_edges[edges_array[j].id].first = edges_array[j].to_cost;
213
214     for(z=0; z<MAX_RULE_LENGTH;++z)
215     {
216       if(edges_array[j].rule[z] > 0)
217       {
218         adjacent_edges[edges_array[j].id].second.push_back(edges_array[j].rule[z]);
219       }
220     }
221
222     if((j < count-1 && edges_array[j].id != edges_array[j+1].id)||(j==count-1))
223     {
224       graph_add_edge<graph_t, edge_descriptor>(graph,
225                                                edges_array[j].id, edges_array[j].source,
226                                                edges_array[j].target, edges_array[j].cost,
227                                                edges_array[j].s_x, edges_array[j].s_y,
228                                                edges_array[j].t_x, edges_array[j].t_y, adjacent_edges);
229
230       if (!directed || (directed && has_reverse_cost))
231       {
232         float8 cost;
233                
234         if (has_reverse_cost)
235         {
236           cost = edges_array[j].reverse_cost;
237         }
238         else
239         {
240           cost = edges_array[j].cost;
241         }
242
243         graph_add_edge<graph_t, edge_descriptor>(graph,
244                                                edges_array[j].id+e_max_id, edges_array[j].target,
245                                                edges_array[j].source, cost,
246                                                edges_array[j].s_x, edges_array[j].s_y,
247                                                edges_array[j].t_x, edges_array[j].t_y, adjacent_edges);
248       }
249
250     adjacent_edges.clear();
251    
252     }
253   }
254    
255   std::map< int, edge_descriptor, std::less<int> > predecessors;
256  
257   edge_descriptor source_edge;
258   edge_descriptor target_edge;
259  
260   bool source_found = false, target_found = false;
261  
262   graph_traits<graph_t>::edge_iterator ei, ei_end;
263   int index;   
264
265   index = 1;
266  
267   for(tie(ei, ei_end) = edges(graph); ei != ei_end; ++ei, ++index)
268     graph[*ei].index = index;   
269    
270   for(tie(ei, ei_end) = edges(graph); ei != ei_end; ++ei)
271   {
272     if(graph[*ei].id == source_edge_id)
273     {
274       source_edge = *ei;
275       source_found = true;
276       break;
277     }
278   }
279
280   if (!source_found)
281   {
282     *err_msg = "Source edge not found";
283     return -1;
284   }
285
286   for(tie(ei, ei_end) = edges(graph); ei != ei_end; ++ei)
287   {
288     if(graph[*ei].id == target_edge_id)
289     {
290       target_edge = *ei;
291       target_found = true;
292       break;
293     }
294   }
295
296   if (!target_found)
297   {
298     *err_msg = "Target edge not found";
299     return -1;
300   }
301
302   std::vector<float8> distances(num_edges(graph));
303  
304   std::vector<default_color_type> edge_colors(num_edges(graph), color_traits<default_color_type>::white());
305
306   property_map<graph_t, std::vector< int > Edge::*>::type history = get(&Edge::history, graph);
307
308   property_map<graph_t, std::size_t Edge::*>::type edge_index = get(&Edge::index, graph);
309
310   property_map<graph_t, float8 Edge::*>::type rank = get(&Edge::rank, graph);
311   property_map<graph_t, float8 Edge::*>::type distance = get(&Edge::distance, graph);
312
313   try
314   {
315     shooting_star_search
316       (graph, source_edge,
317        distance_heuristic<graph_t, float>(graph, target_edge),
318        weight_map(get(&Edge::cost, graph)).
319        weight_map2(get(&Edge::adjacent_edges, graph)).
320        vertex_color_map(get(&Vertex::color, graph)).
321        edge_color_map(get(&Edge::color, graph)).
322        visitor(shooting_star_goal_visitor<edge_descriptor>(target_edge)),
323        edge_index,
324        distance, rank,
325        history,
326        predecessors, e_max_id
327        );
328
329   }
330   catch(found_goal fg) {
331  
332     vector<edge_descriptor> path_vect;
333     int max = MAX_NODES;
334
335     path_vect.push_back(target_edge);
336    
337     while (target_edge != source_edge)
338       {
339         if ((target_edge == predecessors[graph[target_edge].id]) && (predecessors[graph[target_edge].id] != source_edge))
340         {
341           *err_msg = "No path found";
342           return -1;
343            
344         }
345  
346         target_edge = predecessors[graph[target_edge].id];
347
348         if(target_edge == predecessors[graph[target_edge].id] )
349           continue;
350
351         path_vect.push_back(target_edge);
352
353         if (!max--)
354           {
355             *err_msg = "Overflow";
356             return -1;
357           }
358       }
359
360     *path = (path_element_t *) malloc(sizeof(path_element_t) *
361                                       (path_vect.size() + 1));
362     *path_count = path_vect.size();
363
364     for(int i = path_vect.size() - 1, j = 0; i >= 0; i--, j++)
365     {
366       graph_traits < graph_t >::edge_descriptor e;
367
368       e = path_vect.at(i);
369
370       if(graph[e].id > e_max_id)
371         graph[e].id -= e_max_id;
372
373       (*path)[j].edge_id = graph[e].id;
374       (*path)[j].cost = graph[e].cost;
375       (*path)[j].vertex_id = source(e, graph);
376     }
377
378     return EXIT_SUCCESS;
379   }
380
381 }
382
Note: See TracBrowser for help on using the browser.