root/sandbox/orkney/dijkstra.h

Revision 84, 5.0 KB (checked in by anton, 3 years ago)
Line 
1/*
2 * Dijkstra 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#ifndef _DIJKSTRA_H_INCLUDED
23#define _DIJKSTRA_H_INCLUDED
24
25#include "ogr_core.h"
26#include "ogr_feature.h"
27#include "ogr_geometry.h"
28
29#include <boost/config.hpp>
30#include <boost/graph/graph_traits.hpp>
31#include <boost/graph/adjacency_list.hpp>
32#include <boost/graph/dijkstra_shortest_paths.hpp>
33
34#include "algorithm.h"
35
36
37using namespace std;
38using namespace boost;
39
40class Dijkstra : public Algorithm
41{
42  public:
43             Dijkstra(){}
44             Dijkstra( char *nameIn, bool directedIn, bool weightedIn, bool reverseCostIn )
45             : Algorithm( nameIn, directedIn, weightedIn, reverseCostIn ){}
46    virtual ~Dijkstra(){}
47
48    virtual bool addEdge(edge_descriptor *e, OGRFeature *edge, graph_t &graph)
49    {
50      bool inserted; 
51       
52      tie(*e, inserted) = add_edge(edge->GetFieldAsInteger(SOURCE_FIELD),
53                                   edge->GetFieldAsInteger(TARGET_FIELD), graph);
54      return inserted;
55    }
56   
57    virtual void fillFeature(OGRFeature **edges, unsigned int count, edge_descriptor *e, graph_t &graph, int j)
58    {
59      bool inserted = addEdge(e, edges[j], graph);
60
61      graph[*e].cost = edges[j]->GetFieldAsDouble(COST_FIELD);//set cost
62      graph[*e].id = j;//set id
63
64
65      if (!IsDirected() || (IsDirected() && HasReverseCost()))
66      {
67        edge_descriptor *er;
68        //adding an edge for opposite direction
69            bool inserted = addEdge(er, edges[j], graph);
70
71        graph[*er].id = j;//set id
72   
73        if (HasReverseCost())
74            {
75          graph[*er].cost = edges[j]->GetFieldAsDouble(RC_FIELD);//set reverse cost
76            }
77            else
78            {
79              graph[*er].cost = edges[j]->GetFieldAsDouble(COST_FIELD);//set cost
80            }
81      }   
82    }
83
84    virtual int getRoute(int start, int end, OGRFeature **edges, OGRFeature **result, int *resultCount, graph_t &graph)
85    {
86      std::vector<vertex_descriptor> predecessors(num_vertices(graph));
87
88      vertex_descriptor source = vertex(start, graph);
89
90      if (source < 0)
91      {
92        return NO_SOURCE_FOUND;
93      }
94
95      vertex_descriptor target = vertex(end, graph);
96      if (target < 0)
97      {
98        return NO_TARGET_FOUND;
99      }
100
101      std::vector<double> distances(num_vertices(graph));
102
103      dijkstra_shortest_paths(graph, source,
104                              predecessor_map(&predecessors[0]).
105                              weight_map(get(&Edge::cost, graph))
106                              .distance_map(&distances[0]));
107
108      return makeResult(target, source, edges, predecessors, result, resultCount, graph);
109
110    } 
111
112    virtual int makeResult(vertex_descriptor target, vertex_descriptor source,
113                           OGRFeature **edges,
114                           std::vector<vertex_descriptor> &predecessors,
115                           OGRFeature **result, int *resultCount, graph_t &graph)
116    {
117      vector<int> path_vect;
118      int max = MAX_NODES;
119      path_vect.push_back(target);
120
121      while (target != source)
122      {
123            if (target == predecessors[target])
124            {
125              return NO_PATH_FOUND;
126            }
127            target = predecessors[target];
128
129            path_vect.push_back(target);
130            if (!max--)
131            {
132              return RESULT_OVERFLOW;
133            }
134      }
135
136      //*result = (OGRFeature *) malloc(sizeof(OGRFeature) * (path_vect.size() + 1));
137      //Let's try to do it in C++ style
138      result = new OGRFeature* [path_vect.size() + 1];
139      *resultCount = path_vect.size();
140      int i, j;
141
142      for(i = path_vect.size() - 1, j = 0; i >= 0; i--, j++)
143      {
144            graph_traits < graph_t >::vertex_descriptor v_src;
145            graph_traits < graph_t >::vertex_descriptor v_targ;
146            graph_traits < graph_t >::edge_descriptor e;
147            graph_traits < graph_t >::out_edge_iterator out_i, out_end;
148       
149            if (i == 0)
150            {
151              continue;
152            }
153
154            v_src = path_vect.at(i);
155            v_targ = path_vect.at(i - 1);
156
157            for (tie(out_i, out_end) = out_edges(v_src, graph);
158                 out_i != out_end; ++out_i)
159            {
160              graph_traits < graph_t >::vertex_descriptor v, targ;
161              e = *out_i;
162              v = boost::source(e, graph);
163              targ = boost::target(e, graph);
164                                                               
165              if (targ == v_targ)
166              {
167                result[j] = edges[graph[*out_i].id];
168                break;
169              }
170            }
171      }
172
173      return EXIT_SUCCESS;
174    }
175};
176
177#endif
Note: See TracBrowser for help on using the browser.