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