1 : /******************************************************************************
2 : * $Id: gtm.cpp 20996 2010-10-28 18:38:15Z rouault $
3 : *
4 : * Project: GTM Driver
5 : * Purpose: Class for reading, parsing and handling a gtmfile.
6 : * Author: Leonardo de Paula Rosa Piga; http://lampiao.lsc.ic.unicamp.br/~piga
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009, Leonardo de Paula Rosa Piga
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 : #include "gtm.h"
30 :
31 :
32 : /************************************************************************/
33 : /* Methods for dealing with write on files and buffers */
34 : /************************************************************************/
35 60 : void appendDouble(void* pBuffer, double val)
36 : {
37 : CPL_LSBPTR64(&val);
38 60 : memcpy(pBuffer, &val, 8);
39 60 : }
40 :
41 46 : void appendFloat(void* pBuffer, float val)
42 : {
43 : CPL_LSBPTR32(&val)
44 46 : memcpy(pBuffer, &val, 4);
45 46 : }
46 :
47 208 : void appendInt(void* pBuffer, int val)
48 : {
49 : CPL_LSBPTR32(&val)
50 208 : memcpy(pBuffer, &val, 4);
51 208 : }
52 :
53 132 : void appendUChar(void* pBuffer, unsigned char val)
54 : {
55 132 : memcpy(pBuffer, &val, 1);
56 132 : }
57 :
58 120 : void appendUShort(void* pBuffer, unsigned short val)
59 : {
60 : CPL_LSBPTR16(&val)
61 120 : memcpy(pBuffer, &val, 2);
62 120 : }
63 :
64 0 : void writeUChar(VSILFILE* fp, unsigned char val)
65 : {
66 0 : VSIFWriteL(&val, 1, 1, fp);
67 0 : }
68 :
69 16 : void writeDouble(VSILFILE* fp, double val)
70 : {
71 : CPL_LSBPTR64(&val)
72 16 : VSIFWriteL(&val, 1, 8, fp);
73 16 : }
74 :
75 168 : static double readDouble(VSILFILE* fp)
76 : {
77 : double val;
78 168 : VSIFReadL( &val, 1, 8, fp );
79 : CPL_LSBPTR64(&val)
80 168 : return val;
81 : }
82 :
83 84 : static float readFloat(VSILFILE* fp)
84 : {
85 : float val;
86 84 : VSIFReadL( &val, 1, 4, fp );
87 : CPL_LSBPTR32(&val)
88 84 : return val;
89 : }
90 :
91 146 : static int readInt(VSILFILE* fp)
92 : {
93 : int val;
94 146 : VSIFReadL( &val, 1, 4, fp );
95 : CPL_LSBPTR32(&val)
96 146 : return val;
97 : }
98 :
99 28 : static unsigned char readUChar(VSILFILE* fp)
100 : {
101 : unsigned char val;
102 28 : VSIFReadL( &val, 1, 1, fp );
103 28 : return val;
104 : }
105 :
106 144 : static unsigned short readUShort(VSILFILE* fp, int *pbSuccess = NULL)
107 : {
108 : unsigned short val;
109 144 : if (VSIFReadL( &val, 1, 2, fp ) != 2)
110 : {
111 0 : if (pbSuccess) *pbSuccess = FALSE;
112 0 : return 0;
113 : }
114 144 : if (pbSuccess) *pbSuccess = TRUE;
115 : CPL_LSBPTR16(&val)
116 144 : return val;
117 : }
118 :
119 24 : void writeFloat(VSILFILE* fp, float val)
120 : {
121 : CPL_LSBPTR32(&val)
122 24 : VSIFWriteL(&val, 1, 4, fp);
123 24 : }
124 :
125 18 : void writeInt(VSILFILE* fp, int val)
126 : {
127 : CPL_LSBPTR32(&val)
128 18 : VSIFWriteL(&val, 1, 4, fp);
129 18 : }
130 :
131 0 : void writeUShort(VSILFILE* fp, unsigned short val)
132 : {
133 : CPL_LSBPTR16(&val)
134 0 : VSIFWriteL(&val, 1, 2, fp);
135 0 : }
136 :
137 :
138 : /************************************************************************/
139 : /* Implementation of Waypoint Function Members */
140 : /************************************************************************/
141 14 : Waypoint::Waypoint(double latitude,
142 : double longitude,
143 : double altitude,
144 : const char* name,
145 : const char* comment,
146 : int icon,
147 : GIntBig wptdate)
148 : {
149 14 : this->latitude = latitude;
150 14 : this->longitude = longitude;
151 14 : this->altitude = altitude;
152 14 : this->name = CPLStrdup(name);
153 14 : this->comment = CPLStrdup(comment);
154 14 : this->icon = icon;
155 14 : this->wptdate = wptdate;
156 14 : }
157 :
158 14 : Waypoint::~Waypoint()
159 : {
160 14 : CPLFree(name);
161 14 : CPLFree(comment);
162 14 : }
163 :
164 14 : double Waypoint::getLatitude()
165 : {
166 14 : return latitude;
167 : }
168 :
169 14 : double Waypoint::getLongitude()
170 : {
171 14 : return longitude;
172 : }
173 :
174 14 : double Waypoint::getAltitude()
175 : {
176 14 : return altitude;
177 : }
178 :
179 14 : const char* Waypoint::getName()
180 : {
181 14 : return name;
182 : }
183 :
184 14 : const char* Waypoint::getComment()
185 : {
186 14 : return comment;
187 : }
188 :
189 14 : int Waypoint::getIcon()
190 : {
191 14 : return icon;
192 : }
193 :
194 14 : GIntBig Waypoint::getDate()
195 : {
196 14 : return wptdate;
197 : }
198 :
199 : /************************************************************************/
200 : /* Implementation of Track Function Members */
201 : /************************************************************************/
202 14 : Track::Track(const char* pszName,
203 : unsigned char type,
204 : int color)
205 : {
206 14 : this->pszName = CPLStrdup(pszName);
207 14 : this->type = type;
208 14 : this->color = color;
209 14 : nPoints = 0;
210 14 : pasTrackPoints = NULL;
211 14 : }
212 :
213 14 : Track::~Track()
214 : {
215 14 : CPLFree(pszName);
216 14 : pszName = NULL;
217 14 : CPLFree(pasTrackPoints);
218 14 : }
219 :
220 14 : const char* Track::getName() {
221 14 : return pszName;
222 : }
223 :
224 14 : unsigned char Track::getType()
225 : {
226 14 : return type;
227 : }
228 :
229 :
230 14 : int Track::getColor()
231 : {
232 14 : return color;
233 : }
234 :
235 60 : void Track::addPoint(double x, double y, GIntBig datetime, double altitude)
236 : {
237 : pasTrackPoints = (TrackPoint*)
238 60 : CPLRealloc(pasTrackPoints, (nPoints + 1) * sizeof(TrackPoint));
239 60 : pasTrackPoints[nPoints].x = x;
240 60 : pasTrackPoints[nPoints].y = y;
241 60 : pasTrackPoints[nPoints].datetime = datetime;
242 60 : pasTrackPoints[nPoints].altitude = altitude;
243 60 : nPoints ++;
244 60 : }
245 :
246 74 : int Track::getNumPoints()
247 : {
248 74 : return nPoints;
249 : }
250 :
251 60 : const TrackPoint* Track::getPoint(int pointNum)
252 : {
253 60 : if (pointNum >=0 && pointNum < nPoints)
254 60 : return &pasTrackPoints[pointNum];
255 : else
256 0 : return NULL;
257 : }
258 :
259 :
260 : /************************************************************************/
261 : /* Implementation of GTM Function Members */
262 : /************************************************************************/
263 220 : GTM::GTM()
264 : {
265 220 : pGTMFile = NULL;
266 220 : pszFilename = NULL;
267 :
268 220 : nwptstyles = 0;
269 220 : nwpts = 0;
270 220 : ntcks = 0;
271 220 : n_tk = 0;
272 220 : n_maps = 0;
273 220 : headerSize = 0;
274 :
275 220 : firstWaypointOffset = 0;
276 220 : actualWaypointOffset = 0;
277 220 : waypointFetched = 0;
278 :
279 220 : firstTrackpointOffset = 0;
280 220 : actualTrackpointOffset = 0;
281 220 : trackpointFetched = 0;
282 :
283 220 : firstTrackOffset = 0;
284 220 : actualTrackOffset = 0;
285 220 : trackFetched = 0;
286 220 : }
287 :
288 220 : GTM::~GTM()
289 : {
290 220 : CPLFree(pszFilename);
291 220 : if (pGTMFile != NULL)
292 : {
293 140 : VSIFCloseL(pGTMFile);
294 140 : pGTMFile = NULL;
295 : }
296 220 : }
297 :
298 220 : bool GTM::Open(const char* pszFilename)
299 : {
300 :
301 220 : if (pGTMFile != NULL)
302 0 : VSIFCloseL(pGTMFile);
303 :
304 220 : CPLFree(this->pszFilename);
305 220 : this->pszFilename = CPLStrdup(pszFilename);
306 :
307 220 : pGTMFile = VSIFOpenL( pszFilename, "r" );
308 220 : if (pGTMFile == NULL)
309 : {
310 80 : return FALSE;
311 : }
312 140 : return TRUE;
313 : }
314 :
315 :
316 140 : bool GTM::isValid()
317 : {
318 : // 2 bytes - version number
319 : // 10 bytes - "TrackMaker" string
320 : char buffer[13];
321 :
322 : char* szHeader;
323 : short version;
324 :
325 : /* -------------------------------------------------------------------- */
326 : /* If we aren't sure it is GTM, load a header chunk and check */
327 : /* for signs it is GTM */
328 : /* -------------------------------------------------------------------- */
329 140 : size_t nRead = VSIFReadL( buffer, 1, sizeof(buffer)-1, pGTMFile );
330 140 : if (nRead <= 0)
331 : {
332 0 : VSIFCloseL( pGTMFile );
333 0 : pGTMFile = NULL;
334 0 : return FALSE;
335 : }
336 140 : buffer[12] = '\0';
337 :
338 : /* -------------------------------------------------------------------- */
339 : /* If it looks like a GZip header, this may be a .gtz file, so */
340 : /* try opening with the /vsigzip/ prefix */
341 : /* -------------------------------------------------------------------- */
342 140 : if (buffer[0] == 0x1f && ((unsigned char*)buffer)[1] == 0x8b &&
343 : strncmp(pszFilename, "/vsigzip/", strlen("/vsigzip/")) != 0)
344 : {
345 : char* pszGZIPFileName = (char*)CPLMalloc(
346 0 : strlen("/vsigzip/") + strlen(pszFilename) + 1);
347 0 : sprintf(pszGZIPFileName, "/vsigzip/%s", pszFilename);
348 0 : VSILFILE* fp = VSIFOpenL(pszGZIPFileName, "rb");
349 0 : if (fp)
350 : {
351 0 : VSILFILE* pGTMFileOri = pGTMFile;
352 0 : pGTMFile = fp;
353 0 : if (isValid())
354 : {
355 0 : VSIFCloseL(pGTMFileOri);
356 0 : CPLFree(pszGZIPFileName);
357 0 : return TRUE;
358 : }
359 : else
360 : {
361 0 : if (pGTMFile)
362 0 : VSIFCloseL(pGTMFile);
363 0 : pGTMFile = pGTMFileOri;
364 : }
365 : }
366 0 : CPLFree(pszGZIPFileName);
367 : }
368 :
369 140 : version = CPL_LSBINT16PTR(buffer);
370 : /*Skip string length */
371 140 : szHeader = buffer + 2;
372 140 : if (version == 211 && strcmp(szHeader, "TrackMaker") == 0 )
373 : {
374 8 : return TRUE;
375 : }
376 132 : return FALSE;
377 : }
378 :
379 8 : bool GTM::readHeaderNumbers()
380 : {
381 8 : if (pGTMFile == NULL)
382 0 : return FALSE;
383 :
384 :
385 : /* I'm supposing that the user has already checked if the file is
386 : valid. */
387 : /* Also, I'm ignoring some header parameters that are unnecessary
388 : for my purpose. If you want more features, implement it. :-P */
389 :
390 : /* Read Number of Waypoint Styles*/
391 : /* Seek file */
392 8 : if (VSIFSeekL(pGTMFile, NWPTSTYLES_OFFSET, SEEK_SET) != 0)
393 0 : return FALSE;
394 : /* Read nwptstyles */
395 8 : nwptstyles = readInt(pGTMFile);
396 8 : if (nwptstyles < 0)
397 0 : return FALSE;
398 :
399 : /* Read Number of Waypoints */
400 : /* Seek file */
401 8 : if ( VSIFSeekL(pGTMFile, NWPTS_OFFSET, SEEK_SET) != 0)
402 0 : return FALSE;
403 : /* Read nwpts */
404 8 : nwpts = readInt(pGTMFile);
405 8 : if (nwpts < 0)
406 0 : return FALSE;
407 :
408 : /* Read Number of Trackpoints */
409 8 : ntcks = readInt(pGTMFile);
410 8 : if (ntcks < 0)
411 0 : return FALSE;
412 :
413 : /* Read Number of images */
414 : /* Seek file */
415 8 : if ( VSIFSeekL(pGTMFile, NMAPS_OFFSET, SEEK_SET) != 0)
416 0 : return FALSE;
417 : /* read n_maps */
418 8 : n_maps = readInt(pGTMFile);
419 8 : if (n_maps < 0)
420 0 : return FALSE;
421 :
422 : /* Read Number of Tracks */
423 8 : n_tk = readInt(pGTMFile);
424 8 : if (n_tk < 0)
425 0 : return FALSE;
426 :
427 : /* Figure out the header size */
428 8 : headerSize = 99; // Constant size plus size of strings
429 : unsigned short stringSize;
430 :
431 : /* Read gradfont string size */
432 8 : if ( VSIFSeekL(pGTMFile, 99, SEEK_SET) != 0)
433 0 : return FALSE;
434 8 : stringSize = readUShort(pGTMFile);
435 8 : headerSize += stringSize + 2; // String + size field
436 :
437 : /* Read labelfont string size */
438 8 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
439 0 : return FALSE;
440 8 : stringSize = readUShort(pGTMFile);
441 8 : headerSize += stringSize + 2; // String + size field
442 :
443 :
444 : /* Read userfont string size */
445 8 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
446 0 : return FALSE;
447 8 : stringSize = readUShort(pGTMFile);
448 8 : headerSize += stringSize + 2; // String + size field
449 :
450 : /* Read newdatum string size */
451 8 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
452 0 : return FALSE;
453 8 : stringSize = readUShort(pGTMFile);
454 8 : headerSize += stringSize + 2; // String + size field
455 :
456 :
457 :
458 : /* -------------------------------------------------------------------- */
459 : /* Checks if it is using WGS84 datum */
460 : /* -------------------------------------------------------------------- */
461 : /* Read newdatum string size */
462 8 : if ( VSIFSeekL(pGTMFile, headerSize + 34, SEEK_SET) != 0)
463 0 : return FALSE;
464 8 : if (readInt(pGTMFile) != 217)
465 : {
466 : CPLError( CE_Warning, CPLE_AppDefined,
467 : "You are attempting to open a file that is not using WGS84 datum.\n"
468 0 : "Coordinates will be returned as if they were WGS84, but no reprojection will be done.");
469 : }
470 :
471 : /* Look for the offsets */
472 : /* Waypoints */
473 8 : firstWaypointOffset = findFirstWaypointOffset();
474 8 : if (firstWaypointOffset == 0)
475 0 : return FALSE;
476 8 : actualWaypointOffset = firstWaypointOffset;
477 : /* Trackpoints */
478 8 : firstTrackpointOffset = findFirstTrackpointOffset();
479 8 : if (firstTrackpointOffset == 0)
480 0 : return FALSE;
481 8 : actualTrackpointOffset = firstTrackpointOffset;
482 :
483 : /* Tracks */
484 8 : firstTrackOffset = findFirstTrackOffset();
485 8 : if (firstTrackOffset == 0)
486 0 : return FALSE;
487 8 : actualTrackOffset = firstTrackOffset;
488 :
489 8 : return TRUE;
490 : }
491 :
492 : /************************************************************************/
493 : /* Waypoint control functions */
494 : /************************************************************************/
495 12 : int GTM::getNWpts()
496 : {
497 12 : return nwpts;
498 : }
499 :
500 14 : bool GTM::hasNextWaypoint()
501 : {
502 14 : return waypointFetched < nwpts;
503 : }
504 :
505 0 : void GTM::rewindWaypoint()
506 : {
507 0 : actualWaypointOffset = firstWaypointOffset;
508 0 : waypointFetched = 0;
509 0 : }
510 :
511 14 : Waypoint* GTM::fetchNextWaypoint()
512 : {
513 : unsigned short stringSize;
514 :
515 : double latitude, longitude;
516 : char name[11];
517 : char* comment;
518 : unsigned short icon;
519 : int i;
520 : float altitude;
521 : GIntBig wptdate;
522 :
523 : /* Point to the actual waypoint offset */
524 14 : if ( VSIFSeekL(pGTMFile, actualWaypointOffset, SEEK_SET) != 0)
525 0 : return NULL;
526 :
527 14 : latitude = readDouble(pGTMFile);
528 14 : longitude = readDouble(pGTMFile);
529 :
530 14 : if ( !readFile( name, 1, 10 ) )
531 0 : return NULL;
532 : /* Trim string name */
533 66 : for (i = 9; i >= 0; --i)
534 : {
535 66 : if (name[i] != ' ')
536 : {
537 14 : name[i+1] = '\0';
538 14 : break;
539 : }
540 : }
541 14 : if (i < 0)
542 0 : name[0] = '\0';
543 :
544 : /* Read String Length */
545 14 : stringSize = readUShort(pGTMFile);
546 : /* Read Comment String */
547 14 : comment = (char*) VSIMalloc2(sizeof(char), stringSize+1);
548 14 : if ( stringSize != 0 && !readFile( comment, 1, sizeof(char)*stringSize ) )
549 : {
550 0 : CPLFree(comment);
551 0 : return NULL;
552 : }
553 14 : comment[stringSize] = '\0';
554 :
555 : /* Read Icon */
556 14 : icon = readUShort(pGTMFile);
557 :
558 : /* Display number */
559 14 : readUChar(pGTMFile);
560 :
561 : /* Waypoint date */
562 :
563 14 : wptdate = readInt(pGTMFile);
564 14 : if (wptdate != 0)
565 6 : wptdate += GTM_EPOCH;
566 :
567 : /* Rotation text angle */
568 14 : readUShort(pGTMFile);
569 :
570 : /* Altitude */
571 14 : altitude = readFloat(pGTMFile);
572 :
573 : Waypoint* poWaypoint = new Waypoint(latitude, longitude, altitude,
574 14 : name, comment, (int) icon, wptdate);
575 :
576 :
577 : /* Set actual waypoint offset to the next it there is one */
578 14 : ++waypointFetched;
579 14 : if (waypointFetched < nwpts)
580 : {
581 6 : actualWaypointOffset += 8 + 8 + 10 + 2 + stringSize + 2 + 1 + 4 + 2 + 4 + 2;
582 : }
583 :
584 14 : CPLFree(comment);
585 14 : return poWaypoint;
586 : }
587 :
588 :
589 : /************************************************************************/
590 : /* Track control functions */
591 : /************************************************************************/
592 12 : int GTM::getNTracks()
593 : {
594 12 : return n_tk;
595 : }
596 :
597 14 : bool GTM::hasNextTrack()
598 : {
599 14 : return trackFetched < n_tk;
600 : }
601 :
602 0 : void GTM::rewindTrack()
603 : {
604 0 : actualTrackpointOffset = firstTrackpointOffset;
605 0 : actualTrackOffset = firstTrackOffset;
606 0 : trackFetched = 0;
607 0 : trackpointFetched = 0;
608 0 : }
609 :
610 14 : Track* GTM::fetchNextTrack()
611 : {
612 : unsigned short stringSize;
613 :
614 : char* pszName;
615 : unsigned char type;
616 : int color;
617 :
618 :
619 : /* Point to the actual track offset */
620 14 : if ( VSIFSeekL(pGTMFile, actualTrackOffset, SEEK_SET) != 0)
621 0 : return NULL;
622 :
623 :
624 : /* Read string length */
625 14 : stringSize = readUShort(pGTMFile);
626 : /* Read name string */
627 14 : pszName = (char*) VSIMalloc2(sizeof(char), stringSize+1);
628 14 : if ( stringSize != 0 && !readFile( pszName, 1, sizeof(char) * stringSize ) )
629 : {
630 0 : CPLFree(pszName);
631 0 : return NULL;
632 : }
633 14 : pszName[stringSize] = '\0';
634 :
635 : /* Read type */
636 14 : type = readUChar(pGTMFile);
637 :
638 : /* Read color */
639 14 : color = readInt(pGTMFile);
640 :
641 14 : Track* poTrack = new Track(pszName, type, color);
642 :
643 14 : CPLFree(pszName);
644 : /* Adjust actual Track offset */
645 14 : actualTrackOffset = VSIFTellL(pGTMFile) + 7;
646 14 : ++trackFetched;
647 :
648 : /* Now, We read all trackpoints for this track */
649 : double latitude, longitude;
650 : GIntBig datetime;
651 : unsigned char start;
652 : float altitude;
653 : /* NOTE: Parameters are passed by reference */
654 14 : if ( !readTrackPoints(latitude, longitude, datetime, start, altitude) )
655 : {
656 0 : delete poTrack;
657 0 : return NULL;
658 : }
659 :
660 : /* Check if it is the start, if not we have done something wrong */
661 14 : if (start != 1)
662 : {
663 0 : delete poTrack;
664 0 : return NULL;
665 : }
666 14 : poTrack->addPoint(longitude, latitude, datetime, altitude);
667 :
668 56 : do
669 : {
670 : /* NOTE: Parameters are passed by reference */
671 56 : if ( !readTrackPoints(latitude, longitude, datetime, start, altitude) )
672 : {
673 0 : delete poTrack;
674 0 : return NULL;
675 : }
676 56 : if (start == 0)
677 46 : poTrack->addPoint(longitude, latitude, datetime, altitude);
678 : } while(start == 0 && trackpointFetched < ntcks);
679 :
680 : /* We have read one more than necessary, so we adjust the offset */
681 14 : if (trackpointFetched < ntcks)
682 : {
683 10 : actualTrackpointOffset -= 25;
684 10 : --trackpointFetched;
685 : }
686 :
687 14 : return poTrack;
688 : }
689 :
690 :
691 :
692 : /************************************************************************/
693 : /* Private Methods Implementation */
694 : /************************************************************************/
695 8 : vsi_l_offset GTM::findFirstWaypointOffset()
696 : {
697 : /* Skip header and datum */
698 8 : if ( VSIFSeekL(pGTMFile, headerSize + DATUM_SIZE, SEEK_SET) != 0)
699 0 : return 0;
700 :
701 : /* Skip images */
702 : unsigned short stringSize;
703 12 : for (int i = 0; i < n_maps; ++i)
704 : {
705 : /* Read image name string size */
706 4 : stringSize = readUShort(pGTMFile);
707 :
708 : /* skip image name string */
709 4 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
710 0 : return 0;
711 :
712 : /* read image comment string size */
713 4 : stringSize = readUShort(pGTMFile);
714 :
715 : /* skip image comment string */
716 4 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
717 0 : return 0;
718 :
719 : /* skip the others image parameters */
720 4 : if ( VSIFSeekL(pGTMFile, 30, SEEK_CUR) != 0)
721 0 : return 0;
722 : }
723 8 : return VSIFTellL(pGTMFile);
724 : }
725 :
726 :
727 8 : vsi_l_offset GTM::findFirstTrackpointOffset()
728 : {
729 8 : if (firstWaypointOffset == 0)
730 : {
731 0 : firstWaypointOffset = findFirstWaypointOffset();
732 0 : if (firstWaypointOffset == 0)
733 0 : return 0;
734 : }
735 :
736 : /*---------------------------------------------*/
737 : /* We are going to skip the waypoints */
738 : /*---------------------------------------------*/
739 : /* Seek file to the first Waypoint */
740 8 : if (VSIFSeekL(pGTMFile, firstWaypointOffset, SEEK_SET) != 0)
741 0 : return 0;
742 :
743 : unsigned short stringSize;
744 : int bSuccess;
745 : /* Skip waypoints */
746 22 : for (int i = 0; i < nwpts; ++i)
747 : {
748 : /* Seek file to the string size comment field */
749 14 : if (VSIFSeekL(pGTMFile, 26, SEEK_CUR) != 0)
750 0 : return 0;
751 : /* Read string comment size */
752 14 : stringSize = readUShort(pGTMFile, &bSuccess);
753 :
754 : /* Skip to the next Waypoint */
755 14 : if (bSuccess == FALSE || VSIFSeekL(pGTMFile, stringSize + 15, SEEK_CUR) != 0)
756 0 : return 0;
757 : }
758 :
759 : /* Skip waypoint styles */
760 : /* If we don't have waypoints, we don't have waypoint styles, even
761 : though the nwptstyles is telling the contrary. */
762 8 : if (nwpts != 0)
763 : {
764 42 : for (int i = 0; i < nwptstyles; ++i)
765 : {
766 : /* Seek file to the string size facename field */
767 34 : if (VSIFSeekL(pGTMFile, 4, SEEK_CUR) != 0)
768 0 : return 0;
769 :
770 : /* Read string facename size */
771 34 : stringSize = readUShort(pGTMFile, &bSuccess);
772 :
773 : /* Skip to the next Waypoint Style*/
774 34 : if (bSuccess == FALSE || VSIFSeekL(pGTMFile, stringSize + 24, SEEK_CUR) != 0)
775 0 : return 0;
776 : }
777 : }
778 : /* We've found the first track. Return the offset*/
779 8 : return VSIFTellL(pGTMFile);
780 : }
781 :
782 8 : vsi_l_offset GTM::findFirstTrackOffset()
783 : {
784 8 : if (firstTrackpointOffset == 0)
785 : {
786 0 : firstTrackpointOffset = findFirstTrackpointOffset();
787 0 : if (firstTrackpointOffset == 0)
788 0 : return 0;
789 : }
790 : /* First track offset is the first trackpoint offset plus number of
791 : trackpoints time size of a trackpoint*/
792 8 : return (vsi_l_offset) (firstTrackpointOffset + ntcks * 25);
793 : }
794 :
795 70 : bool GTM::readTrackPoints(double& latitude, double& longitude, GIntBig& datetime,
796 : unsigned char& start, float& altitude) {
797 : /* Point to the actual trackpoint offset */
798 70 : if ( VSIFSeekL(pGTMFile, actualTrackpointOffset, SEEK_SET) != 0)
799 0 : return FALSE;
800 :
801 : /* Read latitude */
802 70 : latitude = readDouble(pGTMFile);
803 :
804 : /* Read longitude */
805 70 : longitude = readDouble(pGTMFile);
806 :
807 : /* Read trackpoint date */
808 70 : datetime = readInt(pGTMFile);
809 70 : if (datetime != 0)
810 0 : datetime += GTM_EPOCH;
811 :
812 : /* Read start flag */
813 70 : if ( !readFile( &start, 1, 1 ) )
814 0 : return FALSE;
815 :
816 : /* Read altitude */
817 70 : altitude = readFloat(pGTMFile);
818 :
819 70 : ++trackpointFetched;
820 70 : if (trackpointFetched < ntcks)
821 : {
822 66 : actualTrackpointOffset += 8 + 8 + 4 + 1 + 4;
823 : }
824 70 : return TRUE;
825 : }
826 :
827 112 : bool GTM::readFile(void* pBuffer, size_t nSize, size_t nCount)
828 : {
829 : size_t nRead;
830 112 : nRead = VSIFReadL( pBuffer, nSize, nCount, pGTMFile );
831 112 : if (nRead <= 0)
832 : {
833 0 : VSIFCloseL( pGTMFile );
834 0 : pGTMFile = NULL;
835 0 : return FALSE;
836 : }
837 112 : return TRUE;
838 4029 : }
839 :
840 :
841 :
|