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.

naviguide.cc 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /*
  2. Naviguide Routes
  3. Copyright (C) 2009 Erez Zuler
  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. #include "defs.h"
  17. #include "csv_util.h"
  18. #include "jeeps/gpsmath.h"
  19. #include <QtCore/QDebug>
  20. #include <QtCore/QTextCodec>
  21. #include <math.h>
  22. #define MYNAME "Naviguide"
  23. /************* Specific Naviguide data formats ****************/
  24. /* Naviguide file header */
  25. typedef struct {
  26. uint16_t nof_wp; /* Little endean format */
  27. unsigned char pad1[6]; /* 0xff, 0xff, 0x01, 0x00, 0x06, 0x00 */
  28. char signature[9]; /* cWaypoint */
  29. unsigned char pad2[4]; /* 0x01, 0x00, 0x00, 0x00 */
  30. } ng_file_header_t;
  31. /* Naviguide waypoint/rout data */
  32. typedef struct {
  33. unsigned char pad1[8]; /* 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 */
  34. /* coordination are in old israeli grid */
  35. int32_t East;
  36. int32_t North;
  37. unsigned char pad2[2]; /* 0x01, 0x01 */
  38. uint32_t Alt;
  39. char CommentLength;
  40. } ng_wp_data_t;
  41. typedef struct {
  42. unsigned char pad1[2]; /* 0x01, 0x80 */
  43. uint16_t next_wp;
  44. unsigned char pad2[2]; /* 0x00, 0x00 */
  45. } ng_next_wp_t;
  46. typedef struct {
  47. unsigned char chHeaderLen;
  48. char strName[255];
  49. ng_wp_data_t wp_data;
  50. } ng_wp_no_comment_t;
  51. /* Global variables */
  52. static gbfile* file_in, *file_out;
  53. static uint16_t nof_wp;
  54. static route_head* rte_head;
  55. static ng_file_header_t ng_file_header;
  56. static ng_wp_no_comment_t WPNC;
  57. static ng_next_wp_t ng_next_wp;
  58. static char strComment[101];
  59. /* Process options */
  60. /* wp - process only waypoints */
  61. /* rte - process as route */
  62. /* wprte - Process waypoints and route */
  63. static char* process = NULL;
  64. static char* reorder = NULL;
  65. static int process_rte = 1;
  66. static int reorder_wp = 0;
  67. static char temp_short_name[5];
  68. /* Forward declarations */
  69. static void ng_read_file_header(void);
  70. static
  71. arglist_t ng_args[] = {
  72. {
  73. "output", &process, "'wp' - Create waypoint file , 'rte' - Create route file",
  74. "rte", ARGTYPE_STRING, ARG_NOMINMAX
  75. },
  76. {
  77. "reorder", &reorder, "'n' - Keep the existing wp name, 'y' - rename waypoints",
  78. "n", ARGTYPE_STRING, ARG_NOMINMAX
  79. },
  80. ARG_TERMINATOR
  81. };
  82. /*===================Utilities ==========================================*/
  83. static void
  84. ng_convert_datum(Waypoint* wpt)
  85. {
  86. double lat, lon, east, north, alt;
  87. east = (double) WPNC.wp_data.East;
  88. north = (double) WPNC.wp_data.North;
  89. alt = (double) WPNC.wp_data.Alt;
  90. GPS_Math_ICS_EN_To_WGS84(east, north, &lat, &lon);
  91. wpt->latitude = lat;
  92. wpt->longitude = lon;
  93. wpt->altitude = alt;
  94. }
  95. /*=================== File read/write utilities ==========================================*/
  96. static void
  97. ng_fwrite_wp_data(const QString& s, const QString& d, ng_wp_data_t* wp_data, gbfile* f)
  98. {
  99. int i;
  100. char z[50];
  101. memset(z, 0, 50);
  102. i = s.length();
  103. gbfwrite(&i, 1, 1, f);
  104. gbfwrite(STRFROMUNICODE(s), 1, i, f);
  105. gbfwrite(&wp_data->pad1[0], 8, 1, f);
  106. gbfputint32(wp_data->East, f);
  107. gbfputint32(wp_data->North, f);
  108. gbfwrite(&wp_data->pad2[0], 2, 1, f);
  109. gbfputint32(wp_data->Alt, f);
  110. i = d.length();
  111. gbfwrite(&i, 1, 1, f);
  112. gbfwrite(STRFROMUNICODE(d), 1, i, f);
  113. gbfwrite(z, 44, 1, f);
  114. }
  115. static void
  116. ng_fwrite_next_wp(ng_next_wp_t* nwp, gbfile* f)
  117. {
  118. gbfwrite(nwp->pad1, 2, 1, f);
  119. gbfputint16(nwp->next_wp, f);
  120. gbfwrite(nwp->pad2, 2, 1, f);
  121. }
  122. static void
  123. ng_fread_wp_data(char* d, ng_wp_no_comment_t* wpnc, gbfile* f)
  124. {
  125. int i;
  126. gbfread(&wpnc->chHeaderLen ,sizeof(wpnc->chHeaderLen), 1, f);
  127. gbfread(&wpnc->strName, wpnc->chHeaderLen, 1, f);
  128. wpnc->strName[wpnc->chHeaderLen] = 0;
  129. gbfread(&wpnc->wp_data, 8, 1, f);
  130. wpnc->wp_data.East = gbfgetint32(f);
  131. wpnc->wp_data.North = gbfgetint32(f);
  132. gbfread(&wpnc->wp_data.pad2,2, 1, f);
  133. wpnc->wp_data.Alt = gbfgetint32(f);
  134. gbfread(&wpnc->wp_data.CommentLength, 1, 1, f);
  135. i = (int)wpnc->wp_data.CommentLength;
  136. /* Read the comment field */
  137. gbfread(d, i + 44, 1, f);
  138. }
  139. static void
  140. ng_fread_next_wp(ng_next_wp_t* nwp, gbfile* f)
  141. {
  142. gbfread(&nwp->pad1, 2, 1, f);
  143. nwp->next_wp = gbfgetint16(f);
  144. gbfread(&nwp->pad2, 2, 1, f);
  145. }
  146. /* =================== Write data functions ====================================*/
  147. static void
  148. ng_fill_header_default(void)
  149. {
  150. ng_file_header_t default_header = {
  151. 0x00,
  152. {0xff, 0xff, 0x01, 0x00, 0x09, 0x00},
  153. {'C', 'W', 'a', 'y', 'P', 'o', 'i', 'n', 't'},
  154. {0x01, 0x00, 0x00, 0x00},
  155. };
  156. ng_file_header =default_header;
  157. }
  158. static void
  159. ng_fill_waypoint_default(void)
  160. {
  161. ng_wp_data_t default_wp = {
  162. {0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00},
  163. 0,
  164. 0,
  165. {0x01, 0x01},
  166. 0,
  167. 0x00,
  168. };
  169. ng_next_wp_t default_ng_next_wp = {
  170. {0x01, 0x80},
  171. 0,
  172. {0x00, 0x00},
  173. };
  174. WPNC.wp_data = default_wp;
  175. ng_next_wp = default_ng_next_wp;
  176. }
  177. static void
  178. ng_waypt_rd(const Waypoint* wpt)
  179. {
  180. char z[50];
  181. double lat, lon;
  182. static int current_wp_ix=0;
  183. memset(z, 0, 50);
  184. current_wp_ix++;
  185. ng_fill_waypoint_default();
  186. if (!GPS_Math_WGS84_To_ICS_EN(wpt->latitude, wpt->longitude, &lon, &lat)) {
  187. fatal(MYNAME ": Waypoint %d is out of the israeli grid area", current_wp_ix);
  188. }
  189. WPNC.wp_data.North = (int32_t)lat;
  190. WPNC.wp_data.East = (int32_t)lon;
  191. QString s;
  192. if (reorder_wp) {
  193. sprintf(temp_short_name, "A%03d", current_wp_ix);
  194. s = temp_short_name;
  195. }
  196. else {
  197. s = wpt->shortname;
  198. }
  199. ng_fwrite_wp_data(s, wpt->description, &WPNC.wp_data, file_out);
  200. /* if not Last WP, write the next one index */
  201. if (nof_wp > current_wp_ix) {
  202. ng_next_wp.next_wp = current_wp_ix + 1;
  203. ng_fwrite_next_wp(&ng_next_wp, file_out);
  204. }
  205. }
  206. static void
  207. header_write(void)
  208. {
  209. ng_file_header.nof_wp = nof_wp;
  210. gbfputint16(nof_wp, file_out);
  211. gbfwrite(&ng_file_header.pad1[0], 19, 1, file_out);
  212. }
  213. static void
  214. data_write(void)
  215. {
  216. nof_wp = waypt_count();
  217. if (nof_wp) {
  218. header_write();
  219. waypt_disp_all(ng_waypt_rd);
  220. } else {
  221. nof_wp = route_waypt_count();
  222. if (nof_wp) {
  223. header_write();
  224. route_disp_all(NULL, NULL, ng_waypt_rd);
  225. }
  226. }
  227. }
  228. static void
  229. wr_init(const QString& fname)
  230. {
  231. file_out = gbfopen_le(fname, "wb", MYNAME);
  232. ng_fill_header_default();
  233. if (NULL != reorder)
  234. if (!case_ignore_strcmp(reorder, "y")) {
  235. reorder_wp = 1;
  236. }
  237. }
  238. static void
  239. wr_deinit(void)
  240. {
  241. gbfclose(file_out);
  242. }
  243. /*=========================== Read data functions ==================================*/
  244. static void
  245. rd_init(const QString& fname)
  246. {
  247. file_in = gbfopen_le(fname, "rb", MYNAME);
  248. ng_read_file_header();
  249. if (NULL != process) {
  250. if (!case_ignore_strcmp(process, "wp")) {
  251. process_rte = 0;
  252. }
  253. if (!case_ignore_strcmp(process, "rte")) {
  254. process_rte = 1;
  255. }
  256. }
  257. }
  258. static void
  259. rd_deinit(void)
  260. {
  261. gbfclose(file_in);
  262. file_in = NULL;
  263. }
  264. static void
  265. ng_read_file_header(void)
  266. {
  267. nof_wp = gbfgetint16(file_in);
  268. gbfread(&ng_file_header.pad1[0], 19, 1, file_in);
  269. ng_file_header.nof_wp = nof_wp;
  270. if (strncmp("CWayPoint", ng_file_header.signature, 9)) {
  271. fatal("\nInvalid Naviguide file format\n");
  272. }
  273. }
  274. static void
  275. data_read(void)
  276. {
  277. if (process_rte) {
  278. rte_head = route_head_alloc();
  279. route_add_head(rte_head);
  280. }
  281. for (int n = 0; n < nof_wp; ++n) {
  282. Waypoint* wpt_tmp = new Waypoint;
  283. /* Read waypoint data */
  284. ng_fread_wp_data(strComment, &WPNC, file_in);
  285. if (n < nof_wp - 1) {
  286. /*
  287. gbfread (&ng_next_wp.pad1[0], 2, 1, file_in);
  288. ng_next_wp.next_wp = gbfgetint16 (file_in);
  289. gbfread (&ng_next_wp.pad2[0], 2, 1, file_in);
  290. */
  291. ng_fread_next_wp(&ng_next_wp, file_in);
  292. }
  293. /* Clear commas form the comment for CSV file commonality */
  294. for (unsigned i = 0; i <strlen(strComment); ++i) {
  295. if (strComment[i] == ',') {
  296. strComment[i] = ' ';
  297. }
  298. }
  299. /* put the data in the waypoint structure */
  300. ng_convert_datum(wpt_tmp);
  301. wpt_tmp->shortname = STRTOUNICODE(WPNC.strName);
  302. wpt_tmp->description = STRTOUNICODE(strComment);
  303. if (process_rte) {
  304. route_add_wpt(rte_head, wpt_tmp);
  305. } else {
  306. waypt_add(wpt_tmp);
  307. }
  308. }
  309. } /* data_read */
  310. ff_vecs_t ng_vecs = {
  311. ff_type_file,
  312. FF_CAP_RW_WPT,
  313. rd_init,
  314. wr_init,
  315. rd_deinit,
  316. wr_deinit,
  317. data_read,
  318. data_write,
  319. NULL,
  320. ng_args,
  321. CET_CHARSET_HEBREW, 0
  322. };