You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

googledir.cc 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. Copyright (C) 2002 Robert Lipe, robertlipe+source@gpsbabel.org
  3. Copyright (C) 2012 Guilhem Bonnefille, guilhem.bonnefille@gmail.com
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  15. */
  16. /*
  17. * Parse the output of the following command:
  18. * curl "http://maps.googleapis.com/maps/api/directions/xml?origin='Albi,%20france'&destination='toulouse,%20france'&sensor=false" > google-direction.xml
  19. *
  20. * For more information, check:
  21. * https://developers.google.com/maps/documentation/directions/
  22. */
  23. #include "defs.h"
  24. #include "xmlgeneric.h"
  25. #include <QtCore/QXmlStreamAttributes>
  26. static QString encoded_points;
  27. static QString instructions;
  28. static short_handle desc_handle;
  29. #define MYNAME "googledir"
  30. static xg_callback goog_points, goog_poly_e;
  31. static xg_callback goog_instr;
  32. static
  33. xg_tag_mapping google_map[] = {
  34. { goog_points, cb_cdata, "/DirectionsResponse/route/overview_polyline/points" },
  35. { goog_poly_e, cb_end, "/DirectionsResponse/route/overview_polyline" },
  36. { goog_points, cb_cdata, "/DirectionsResponse/route/leg/step/polyline/points" },
  37. { goog_poly_e, cb_end, "/DirectionsResponse/route/leg/step" },
  38. { goog_instr, cb_cdata, "/DirectionsResponse/route/leg/step/html_instructions" },
  39. { NULL, (xg_cb_type)0, NULL }
  40. };
  41. void
  42. goog_points(xg_string args, const QXmlStreamAttributes*)
  43. {
  44. encoded_points += args;
  45. }
  46. void
  47. goog_instr(xg_string args, const QXmlStreamAttributes*)
  48. {
  49. instructions += args;
  50. }
  51. static int goog_step = 0;
  52. long
  53. decode_goog64(const QByteArray& str, int& pos)
  54. {
  55. long result = 0;
  56. unsigned char shift = 0;
  57. if (pos >= str.size()) {
  58. return 0;
  59. }
  60. unsigned char c;
  61. do {
  62. c = str.at(pos++) - '?';
  63. result |= (c & 31) << shift;
  64. shift += 5;
  65. } while (c & ~31);
  66. if (result & 1) {
  67. result = ~result;
  68. }
  69. return result/2;
  70. }
  71. static void
  72. goog_poly_e(xg_string args, const QXmlStreamAttributes*)
  73. {
  74. long lat = 0;
  75. long lon = 0;
  76. const QByteArray qbstr = encoded_points.toUtf8();
  77. route_head* routehead = route_head_alloc();
  78. if (args == "overview_polyline") {
  79. routehead->rte_name = "overview";
  80. routehead->rte_desc = "Overview";
  81. } else {
  82. goog_step++;
  83. routehead->rte_name = QString("step%1").arg(goog_step, 3, 10, QChar('0'));
  84. if (instructions == NULL) {
  85. routehead->rte_desc = QString("Step %1").arg(goog_step);
  86. } else {
  87. utf_string utf;
  88. utf.is_html = 1;
  89. utf.utfstring = instructions;
  90. char *s = strip_html(&utf);
  91. routehead->rte_desc = s;
  92. xfree(s);
  93. instructions = QString();
  94. }
  95. }
  96. route_add_head(routehead);
  97. for (int qbpos=0; qbpos < qbstr.size();) {
  98. lat += decode_goog64(qbstr, qbpos);
  99. lon += decode_goog64(qbstr, qbpos);
  100. {
  101. Waypoint* wpt_tmp = new Waypoint;
  102. wpt_tmp->latitude = lat / 100000.0;
  103. wpt_tmp->longitude = lon / 100000.0;
  104. route_add_wpt(routehead, wpt_tmp);
  105. }
  106. }
  107. encoded_points = QString();
  108. instructions = QString();
  109. }
  110. static void
  111. google_rd_init(const QString& fname)
  112. {
  113. desc_handle = mkshort_new_handle();
  114. setshort_length(desc_handle, 12);
  115. // leave default of UTF-8 unless xml file overrides with encoding=
  116. xml_init(fname, google_map, NULL);
  117. }
  118. static void
  119. google_read(void)
  120. {
  121. xml_read();
  122. encoded_points = QString();
  123. instructions = QString();
  124. }
  125. static void
  126. google_rd_deinit(void)
  127. {
  128. xml_deinit();
  129. mkshort_del_handle(&desc_handle);
  130. }
  131. ff_vecs_t google_dir_vecs = {
  132. ff_type_file,
  133. { ff_cap_none, ff_cap_read, ff_cap_none},
  134. google_rd_init,
  135. NULL,
  136. google_rd_deinit,
  137. NULL,
  138. google_read,
  139. NULL,
  140. NULL,
  141. NULL,
  142. CET_CHARSET_UTF8, 1 /* CET-REVIEW */
  143. };