pgRouting  2.2
pgRouting extends the PostGIS / PostgreSQL geospatial database to provide geospatial routing functionality.
 All Classes Functions Variables Pages
pgRouting.cpp
1 /*PGR-GNU*****************************************************************
2 
3 Copyright (c) 2015 pgRouting developers
4 Mail: project@pgrouting.org
5 
6 ------
7 
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 
22 ********************************************************************PGR-GNU*/
23 
24 /************************************************************************/
25 /* $Id: MainP.cpp 65 2010-09-08 06:48:36Z yan.qi.asu $ */
26 /************************************************************************/
27 #include <boost/config.hpp>
28 #include <string>
29 #include <boost/program_options.hpp>
30 namespace po = boost::program_options;
31 
32 #include <boost/graph/adjacency_list.hpp>
33 
34 #include <iostream>
35 #include <sstream>
36 #include <fstream>
37 #include <deque>
38 #include <unistd.h>
39 #include <libpq-fe.h>
40 
41 
42 #include "postgres.h"
43 #include "./../../common/src/pgr_types.h"
44 #include "./../../common/src/basePath_SSEC.hpp"
45 #include "./../../dijkstra/src/pgr_dijkstra.hpp"
46 #include "./../../warshall/src/pgr_warshall.hpp"
47 #include "./../../ksp/src/pgr_ksp.hpp"
48 #include "./driving.cpp"
49 #include "./dijkstra.hpp"
50 #include "./ksp.cpp"
51 #include "./warshall.hpp"
52 
53 
54 
55 /****************************************
56 SIMULATES THE C CODE THAT LOADS THE DATA
57 ****************************************/
58 void import_from_file(const std::string &input_file_name, pgr_edge_t *edges, unsigned int *count, int64_t start_vertex, int64_t end_vertex, bool &found) {
59  const char* file_name = input_file_name.c_str();
60 
61  std::ifstream ifs(file_name);
62  if (!ifs) {
63  std::cerr << "The file " << file_name << " can not be opened!" << std::endl;
64  exit(1);
65  }
66 
67  ifs >> (*count);
68 
69  long edge_id; // , start_id, end_id;
70  //double edge_weight, reverse_weight;
71  bool s_found = false;
72  bool t_found = false;
73 
74  unsigned int i = 0;
75  while (i < (*count) && ifs >> edge_id) {
76  if (edge_id == -1) break;
77  edges[i].id = edge_id;
78  ifs >> edges[i].source;
79  ifs >> edges[i].target;
80  ifs >> edges[i].cost;
81  ifs >> edges[i].reverse_cost;
82  // when loading checking if start and end are found
83  if (!s_found)
84  s_found = ((edges[i].source == start_vertex) || (edges[i].target == end_vertex));
85  if (!t_found)
86  t_found = ((edges[i].source == end_vertex) || (edges[i].target == end_vertex));
87  i++;
88  }
89  ifs.close();
90  found = s_found && t_found;
91 }
92 
93 void get_options_description(po::options_description &od_desc) {
94  od_desc.add_options()
95  ("help", "Produce this help message.")
96  ("test,t", po::value<bool>()->default_value(true),
97  "For testing purposes.")
98  ("dbname,d", po::value<std::string>()->required(),
99  "Specifies the name of the database to connect to.")
100  ("host,h", po::value<std::string>()->default_value("localhost"),
101  "Specifies the host name of the machine on which the server is running.")
102  ("port,p", po::value<std::string>()->default_value("5432"),
103  "Port number to connect to at the server host.")
104  ("username,U", po::value<std::string>()->default_value(getlogin()),
105  "Connect to the database as the user username instead of the default.\n (You must have permission to do so, of course.)")
106  ("password,W", po::value<std::string>()->default_value(""),
107  "User's the password.\n")
108 #if 0
109  ("no-password,w", po::value<bool>()->implicit_value(false),
110  "Never issue a password prompt.\n"
111  "If the server requires password authentication and a password is not available by other means such as a .pgpass file, the connection attempt will fail.\n"
112  "This option can be useful in batch jobs and scripts where no user is present to enter a password.")
113 #endif
114  ;
115 }
116 
117 
118 int process_command_line(
119  po::variables_map &vm,
120  po::options_description &od_desc) {
121 
122  if (vm.count("help")) {
123  std::cout << od_desc << "\n";
124  return 0;
125  }
126 
127  if (vm.count("dbname"))
128  std::cout << "dbname = " << vm["dbname"].as<std::string>() << "\n";
129  else
130  std::cout << "Parameter: dbname missing\n";
131 
132  if (vm.count("host"))
133  std::cout << "host = " << vm["host"].as<std::string>() << "\n";
134  else
135  std::cout << "Parameter: host missing\n";
136 
137  if (vm.count("port"))
138  std::cout << "port = " << vm["port"].as<std::string>() << "\n";
139  else
140  std::cout << "Parameter: port missing\n";
141 
142  if (vm.count("username"))
143  std::cout << "username = " << vm["username"].as<std::string>() << "\n";
144  else
145  std::cout << "Parameter: username missing\n";
146 
147  if (vm.count("dbname") & vm.count("username") & vm.count("host")) {
148  std::cout << "Parameters: \n"
149  << vm["dbname"].as<std::string>() << "\n"
150  << vm["username"].as<std::string>() << "\n"
151  << vm["host"].as<std::string>() << ".\n";
152  return 2;
153  } else {
154  std::cout << "Missing parameter.\n";
155  std::cout << od_desc << "\n";
156  return 1;
157  }
158 }
159 
160 
161 static void
162 exit_nicely(PGconn *conn)
163 {
164  PQfinish(conn);
165  exit(1);
166 }
167 
168 
169 
170 template <typename G>
171 void process(G graph, pgr_edge_t *data_edges, int row_count) {
172  graph.graph_insert_data(data_edges, row_count);
173  std::vector<int64_t> targets;
174  std::string::size_type sz;
175 
176 
177  // read the command and break into tokens
178  std::string cmd;
179  std::string buf;
180  std::vector<std::string> tokens;
181  while (true) {
182  std::cout << "\n\n\n\n\t\t COMMANDS\n\n "
183  << "\tWARSHALL\n"
184  << "\twarshall\n"
185 
186  << "\n\tKSP\n"
187  << "(Input the command separating with spaces)\n"
188  << "\tksp from to \n"
189 
190  << "\n\tDIJKSTRA\n"
191  << "(Input the command separating with spaces)\n"
192  << "\tdijkstra from to \n"
193  << "\tdijkstra from to1 to2 to3\n\n"
194 
195  << "\n\tDRIVING DISTANCE\n"
196  << "(Use kewywords)\n"
197  << "\tdrivDist from <id> [<id> ...] dist <distance> [equi]\n"
198 
199  << "\n\tFINISH\n"
200  << "\tend\n\n"
201  << ">>>";
202  tokens.clear();
203  targets.clear();
204  cmd = "";
205  std::getline(std::cin, cmd);
206  std::stringstream ss(cmd);
207  while (ss >> buf) {
208  tokens.push_back(buf);
209  }
210 
211  if (tokens.size() == 0) {
212  std::cout << "No command received\n";
213  continue;
214  }
215 
216  if (tokens[0].compare("end")==0) return;
217 
218  if (tokens[0].compare("dijkstra") != 0
219  && tokens[0].compare("warshall") != 0
220  && tokens[0].compare("ksp") != 0
221  && tokens[0].compare("drivDist") != 0 ) {
222  std::cout << "Command: " << cmd << " not found\n";
223  continue;
224  }
225 
226 
227  if (tokens[0].compare("dijkstra") == 0) {
228  process_dijkstra(graph, tokens);
229  } else if (tokens[0].compare("ksp") == 0) {
230  process_ksp(graph, tokens);
231  } else if (tokens[0].compare("warshall") == 0) {
232  process_warshall(graph, tokens);
233  } else {
234  process_drivingDistance(graph, tokens);
235  }
236  }
237 }
238 
239 
240 
241 int main(int ac, char* av[]) {
242  po::options_description od_desc("Allowed options");
243  get_options_description(od_desc);
244 
245  po::variables_map vm;
246  po::store(po::parse_command_line(ac, av, od_desc), vm);
247  if (vm.count("help")) {
248  std::cout << od_desc << "\n";
249  return 0;
250  }
251 
252  try{
253  po::notify(vm);
254  }
255  catch(...){
256  std::cout << od_desc << "\n";
257  return 0;
258  }
259 
260  auto ret_val = process_command_line(vm, od_desc);
261  if (ret_val != 2) return ret_val;
262 
263 
264  auto db_dbase(vm["dbname"].as<std::string>());
265  db_dbase = "dbname = " + db_dbase;
266  auto db_host(vm["host"].as<std::string>());
267  auto db_port(vm["port"].as<std::string>());
268  auto db_username(vm["username"].as<std::string>());
269  auto db_pwd(vm["password"].as<std::string>());
270  auto test(vm["test"].as<bool>());
271  //auto db_no_pwd(vm["no-password"].as<std::string>());
272 
273  const char *conninfo = db_dbase.c_str();
274  PGconn *conn;
275  PGresult *res;
276  int rec_count, col_count;
277 
278 
279  conn = PQconnectdb(conninfo);
280  /* Check to see that the backend connection was successfully made */
281  if (PQstatus(conn) != CONNECTION_OK)
282  {
283  fprintf(stderr, "Connection to database failed: %s",
284  PQerrorMessage(conn));
285  exit_nicely(conn);
286  exit(0);
287  }
288 
289  std::string data_sql;
290  if (test) {
291  data_sql = "select id, source, target, cost, -1 as reverse_cost from table1 order by id";
292  // data_sql = "select id, source, target, cost, reverse_cost from edge_table order by id";
293  } else {
294  std::cout << "Input data query: ";
295  std::getline (std::cin,data_sql);
296  }
297  std::cout << "\nThe data is from:" << data_sql <<"\n";
298 
299  res = PQexec(conn, data_sql.c_str());
300 
301  if (PQresultStatus(res) != PGRES_TUPLES_OK) {
302  std::cout << "We did not get any data!\n";
303  exit_nicely(conn);
304  exit(1);
305  }
306 
307  rec_count = PQntuples(res);
308  col_count = PQnfields(res);
309  if (col_count > 5 || col_count < 4) {
310  std::cout << "Max number of columns 5\n";
311  std::cout << "Min number of columns 4\n";
312  exit_nicely(conn);
313  exit(1);
314  }
315 
316  auto id_fnum = PQfnumber(res, "id");
317  auto source_fnum = PQfnumber(res, "source");
318  auto target_fnum = PQfnumber(res, "target");
319  auto cost_fnum = PQfnumber(res, "cost");
320  auto reverse_fnum = PQfnumber(res, "reverse_cost");
321 
322 
323 
324  pgr_edge_t *data_edges;
325  data_edges = (pgr_edge_t *) malloc(rec_count * sizeof(pgr_edge_t));
326 
327 
328  printf("We received %d records.\n", rec_count);
329  puts("==========================");
330 
331 
332 
333  std::string::size_type sz;
334  std::string str;
335 
336  for (int row = 0; row < rec_count; ++row) {
337  str = std::string(PQgetvalue(res, row, id_fnum));
338  data_edges[row].id = stol(str, &sz);
339 
340  str = std::string(PQgetvalue(res, row, source_fnum));
341  data_edges[row].source = stol(str, &sz);
342 
343  str = std::string(PQgetvalue(res, row, target_fnum));
344  data_edges[row].target = stol(str, &sz);
345 
346  str = std::string(PQgetvalue(res, row, cost_fnum));
347  data_edges[row].cost = stod(str, &sz);
348 
349  if (reverse_fnum != -1) {
350  str = std::string(PQgetvalue(res, row, reverse_fnum));
351  data_edges[row].reverse_cost = stod(str, &sz);
352  }
353 #if 0
354  std::cout << "\tid: " << data_edges[row].id << "\t";
355  std::cout << "\tsource: " << data_edges[row].source << "\t";
356  std::cout << "\ttarget: " << data_edges[row].target << "\t";
357  std::cout << "\tcost: " << data_edges[row].cost << "\t";
358  if (reverse_fnum != -1) {
359  std::cout << "\treverse: " << data_edges[row].reverse_cost << "\t";
360  }
361  std::cout << "\n";
362 #endif
363  }
364 
365 
366  puts("==========================");
367 
368  PQclear(res);
369 
370  PQfinish(conn);
371 
372 
374 
375  std::string directed;
376  std::cout << "Is the graph directed [N,n]? default[Y]";
377  std::getline(std::cin,directed);
378  graphType gType = (directed.compare("N")==0 || directed.compare("n")==0)? UNDIRECTED: DIRECTED;
379  bool directedFlag = (directed.compare("N")==0 || directed.compare("n")==0)? false: true;
380 
381 
382  const int initial_size = rec_count;
383 
384 
385  Pgr_base_graph< DirectedGraph > digraph(gType, initial_size);
386  Pgr_base_graph< UndirectedGraph > undigraph(gType, initial_size);
387 
388  if (directedFlag) {
389  process(digraph, data_edges, rec_count);
390  } else {
391  process(undigraph, data_edges, rec_count);
392  }
393 
394 }
395 
396