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 30 : void appendDouble(void* pBuffer, double val)
36 : {
37 : CPL_LSBPTR64(&val);
38 30 : memcpy(pBuffer, &val, 8);
39 30 : }
40 :
41 23 : void appendFloat(void* pBuffer, float val)
42 : {
43 : CPL_LSBPTR32(&val)
44 23 : memcpy(pBuffer, &val, 4);
45 23 : }
46 :
47 104 : void appendInt(void* pBuffer, int val)
48 : {
49 : CPL_LSBPTR32(&val)
50 104 : memcpy(pBuffer, &val, 4);
51 104 : }
52 :
53 66 : void appendUChar(void* pBuffer, unsigned char val)
54 : {
55 66 : memcpy(pBuffer, &val, 1);
56 66 : }
57 :
58 60 : void appendUShort(void* pBuffer, unsigned short val)
59 : {
60 : CPL_LSBPTR16(&val)
61 60 : memcpy(pBuffer, &val, 2);
62 60 : }
63 :
64 0 : void writeUChar(VSILFILE* fp, unsigned char val)
65 : {
66 0 : VSIFWriteL(&val, 1, 1, fp);
67 0 : }
68 :
69 8 : void writeDouble(VSILFILE* fp, double val)
70 : {
71 : CPL_LSBPTR64(&val)
72 8 : VSIFWriteL(&val, 1, 8, fp);
73 8 : }
74 :
75 84 : static double readDouble(VSILFILE* fp)
76 : {
77 : double val;
78 84 : VSIFReadL( &val, 1, 8, fp );
79 : CPL_LSBPTR64(&val)
80 84 : return val;
81 : }
82 :
83 42 : static float readFloat(VSILFILE* fp)
84 : {
85 : float val;
86 42 : VSIFReadL( &val, 1, 4, fp );
87 : CPL_LSBPTR32(&val)
88 42 : return val;
89 : }
90 :
91 73 : static int readInt(VSILFILE* fp)
92 : {
93 : int val;
94 73 : VSIFReadL( &val, 1, 4, fp );
95 : CPL_LSBPTR32(&val)
96 73 : return val;
97 : }
98 :
99 14 : static unsigned char readUChar(VSILFILE* fp)
100 : {
101 : unsigned char val;
102 14 : VSIFReadL( &val, 1, 1, fp );
103 14 : return val;
104 : }
105 :
106 72 : static unsigned short readUShort(VSILFILE* fp, int *pbSuccess = NULL)
107 : {
108 : unsigned short val;
109 72 : if (VSIFReadL( &val, 1, 2, fp ) != 2)
110 : {
111 0 : if (pbSuccess) *pbSuccess = FALSE;
112 0 : return 0;
113 : }
114 72 : if (pbSuccess) *pbSuccess = TRUE;
115 : CPL_LSBPTR16(&val)
116 72 : return val;
117 : }
118 :
119 12 : void writeFloat(VSILFILE* fp, float val)
120 : {
121 : CPL_LSBPTR32(&val)
122 12 : VSIFWriteL(&val, 1, 4, fp);
123 12 : }
124 :
125 9 : void writeInt(VSILFILE* fp, int val)
126 : {
127 : CPL_LSBPTR32(&val)
128 9 : VSIFWriteL(&val, 1, 4, fp);
129 9 : }
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 7 : 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 7 : this->latitude = latitude;
150 7 : this->longitude = longitude;
151 7 : this->altitude = altitude;
152 7 : this->name = CPLStrdup(name);
153 7 : this->comment = CPLStrdup(comment);
154 7 : this->icon = icon;
155 7 : this->wptdate = wptdate;
156 7 : }
157 :
158 7 : Waypoint::~Waypoint()
159 : {
160 7 : CPLFree(name);
161 7 : CPLFree(comment);
162 7 : }
163 :
164 7 : double Waypoint::getLatitude()
165 : {
166 7 : return latitude;
167 : }
168 :
169 7 : double Waypoint::getLongitude()
170 : {
171 7 : return longitude;
172 : }
173 :
174 7 : double Waypoint::getAltitude()
175 : {
176 7 : return altitude;
177 : }
178 :
179 7 : const char* Waypoint::getName()
180 : {
181 7 : return name;
182 : }
183 :
184 7 : const char* Waypoint::getComment()
185 : {
186 7 : return comment;
187 : }
188 :
189 7 : int Waypoint::getIcon()
190 : {
191 7 : return icon;
192 : }
193 :
194 7 : GIntBig Waypoint::getDate()
195 : {
196 7 : 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 81 : GTM::GTM()
264 : {
265 81 : pGTMFile = NULL;
266 81 : pszFilename = NULL;
267 :
268 81 : nwptstyles = 0;
269 81 : nwpts = 0;
270 81 : ntcks = 0;
271 81 : n_tk = 0;
272 81 : n_maps = 0;
273 81 : headerSize = 0;
274 :
275 81 : firstWaypointOffset = 0;
276 81 : actualWaypointOffset = 0;
277 81 : waypointFetched = 0;
278 :
279 81 : firstTrackpointOffset = 0;
280 81 : actualTrackpointOffset = 0;
281 81 : trackpointFetched = 0;
282 :
283 81 : firstTrackOffset = 0;
284 81 : actualTrackOffset = 0;
285 81 : trackFetched = 0;
286 81 : }
287 :
288 81 : GTM::~GTM()
289 : {
290 81 : CPLFree(pszFilename);
291 81 : if (pGTMFile != NULL)
292 : {
293 44 : VSIFCloseL(pGTMFile);
294 44 : pGTMFile = NULL;
295 : }
296 81 : }
297 :
298 81 : bool GTM::Open(const char* pszFilename)
299 : {
300 :
301 81 : if (pGTMFile != NULL)
302 0 : VSIFCloseL(pGTMFile);
303 :
304 81 : CPLFree(this->pszFilename);
305 81 : this->pszFilename = CPLStrdup(pszFilename);
306 :
307 81 : pGTMFile = VSIFOpenL( pszFilename, "r" );
308 81 : if (pGTMFile == NULL)
309 : {
310 37 : return FALSE;
311 : }
312 44 : return TRUE;
313 : }
314 :
315 :
316 44 : 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 44 : size_t nRead = VSIFReadL( buffer, 1, sizeof(buffer)-1, pGTMFile );
330 44 : if (nRead <= 0)
331 : {
332 0 : VSIFCloseL( pGTMFile );
333 0 : pGTMFile = NULL;
334 0 : return FALSE;
335 : }
336 44 : 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 44 : 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 44 : version = CPL_LSBINT16PTR(buffer);
370 : /*Skip string length */
371 44 : szHeader = buffer + 2;
372 44 : if (version == 211 && strcmp(szHeader, "TrackMaker") == 0 )
373 : {
374 4 : return TRUE;
375 : }
376 40 : return FALSE;
377 : }
378 :
379 4 : bool GTM::readHeaderNumbers()
380 : {
381 4 : 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 4 : if (VSIFSeekL(pGTMFile, NWPTSTYLES_OFFSET, SEEK_SET) != 0)
393 0 : return FALSE;
394 : /* Read nwptstyles */
395 4 : nwptstyles = readInt(pGTMFile);
396 4 : if (nwptstyles < 0)
397 0 : return FALSE;
398 :
399 : /* Read Number of Waypoints */
400 : /* Seek file */
401 4 : if ( VSIFSeekL(pGTMFile, NWPTS_OFFSET, SEEK_SET) != 0)
402 0 : return FALSE;
403 : /* Read nwpts */
404 4 : nwpts = readInt(pGTMFile);
405 4 : if (nwpts < 0)
406 0 : return FALSE;
407 :
408 : /* Read Number of Trackpoints */
409 4 : ntcks = readInt(pGTMFile);
410 4 : if (ntcks < 0)
411 0 : return FALSE;
412 :
413 : /* Read Number of images */
414 : /* Seek file */
415 4 : if ( VSIFSeekL(pGTMFile, NMAPS_OFFSET, SEEK_SET) != 0)
416 0 : return FALSE;
417 : /* read n_maps */
418 4 : n_maps = readInt(pGTMFile);
419 4 : if (n_maps < 0)
420 0 : return FALSE;
421 :
422 : /* Read Number of Tracks */
423 4 : n_tk = readInt(pGTMFile);
424 4 : if (n_tk < 0)
425 0 : return FALSE;
426 :
427 : /* Figure out the header size */
428 4 : headerSize = 99; // Constant size plus size of strings
429 : unsigned short stringSize;
430 :
431 : /* Read gradfont string size */
432 4 : if ( VSIFSeekL(pGTMFile, 99, SEEK_SET) != 0)
433 0 : return FALSE;
434 4 : stringSize = readUShort(pGTMFile);
435 4 : headerSize += stringSize + 2; // String + size field
436 :
437 : /* Read labelfont string size */
438 4 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
439 0 : return FALSE;
440 4 : stringSize = readUShort(pGTMFile);
441 4 : headerSize += stringSize + 2; // String + size field
442 :
443 :
444 : /* Read userfont string size */
445 4 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
446 0 : return FALSE;
447 4 : stringSize = readUShort(pGTMFile);
448 4 : headerSize += stringSize + 2; // String + size field
449 :
450 : /* Read newdatum string size */
451 4 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
452 0 : return FALSE;
453 4 : stringSize = readUShort(pGTMFile);
454 4 : 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 4 : if ( VSIFSeekL(pGTMFile, headerSize + 34, SEEK_SET) != 0)
463 0 : return FALSE;
464 4 : 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 4 : firstWaypointOffset = findFirstWaypointOffset();
474 4 : if (firstWaypointOffset == 0)
475 0 : return FALSE;
476 4 : actualWaypointOffset = firstWaypointOffset;
477 : /* Trackpoints */
478 4 : firstTrackpointOffset = findFirstTrackpointOffset();
479 4 : if (firstTrackpointOffset == 0)
480 0 : return FALSE;
481 4 : actualTrackpointOffset = firstTrackpointOffset;
482 :
483 : /* Tracks */
484 4 : firstTrackOffset = findFirstTrackOffset();
485 4 : if (firstTrackOffset == 0)
486 0 : return FALSE;
487 4 : actualTrackOffset = firstTrackOffset;
488 :
489 4 : return TRUE;
490 : }
491 :
492 : /************************************************************************/
493 : /* Waypoint control functions */
494 : /************************************************************************/
495 6 : int GTM::getNWpts()
496 : {
497 6 : return nwpts;
498 : }
499 :
500 7 : bool GTM::hasNextWaypoint()
501 : {
502 7 : return waypointFetched < nwpts;
503 : }
504 :
505 0 : void GTM::rewindWaypoint()
506 : {
507 0 : actualWaypointOffset = firstWaypointOffset;
508 0 : waypointFetched = 0;
509 0 : }
510 :
511 7 : 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 7 : if ( VSIFSeekL(pGTMFile, actualWaypointOffset, SEEK_SET) != 0)
525 0 : return NULL;
526 :
527 7 : latitude = readDouble(pGTMFile);
528 7 : longitude = readDouble(pGTMFile);
529 :
530 7 : if ( !readFile( name, 1, 10 ) )
531 0 : return NULL;
532 : /* Trim string name */
533 33 : for (i = 9; i >= 0; --i)
534 : {
535 33 : if (name[i] != ' ')
536 : {
537 7 : name[i+1] = '\0';
538 7 : break;
539 : }
540 : }
541 7 : if (i < 0)
542 0 : name[0] = '\0';
543 :
544 : /* Read String Length */
545 7 : stringSize = readUShort(pGTMFile);
546 : /* Read Comment String */
547 7 : comment = (char*) VSIMalloc2(sizeof(char), stringSize+1);
548 7 : if ( stringSize != 0 && !readFile( comment, 1, sizeof(char)*stringSize ) )
549 : {
550 0 : CPLFree(comment);
551 0 : return NULL;
552 : }
553 7 : comment[stringSize] = '\0';
554 :
555 : /* Read Icon */
556 7 : icon = readUShort(pGTMFile);
557 :
558 : /* Display number */
559 7 : readUChar(pGTMFile);
560 :
561 : /* Waypoint date */
562 :
563 7 : wptdate = readInt(pGTMFile);
564 7 : if (wptdate != 0)
565 3 : wptdate += GTM_EPOCH;
566 :
567 : /* Rotation text angle */
568 7 : readUShort(pGTMFile);
569 :
570 : /* Altitude */
571 7 : altitude = readFloat(pGTMFile);
572 :
573 : Waypoint* poWaypoint = new Waypoint(latitude, longitude, altitude,
574 7 : name, comment, (int) icon, wptdate);
575 :
576 :
577 : /* Set actual waypoint offset to the next it there is one */
578 7 : ++waypointFetched;
579 7 : if (waypointFetched < nwpts)
580 : {
581 3 : actualWaypointOffset += 8 + 8 + 10 + 2 + stringSize + 2 + 1 + 4 + 2 + 4 + 2;
582 : }
583 :
584 7 : CPLFree(comment);
585 7 : return poWaypoint;
586 : }
587 :
588 :
589 : /************************************************************************/
590 : /* Track control functions */
591 : /************************************************************************/
592 6 : int GTM::getNTracks()
593 : {
594 6 : return n_tk;
595 : }
596 :
597 7 : bool GTM::hasNextTrack()
598 : {
599 7 : 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 7 : 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 7 : if ( VSIFSeekL(pGTMFile, actualTrackOffset, SEEK_SET) != 0)
621 0 : return NULL;
622 :
623 :
624 : /* Read string length */
625 7 : stringSize = readUShort(pGTMFile);
626 : /* Read name string */
627 7 : pszName = (char*) VSIMalloc2(sizeof(char), stringSize+1);
628 7 : if ( stringSize != 0 && !readFile( pszName, 1, sizeof(char) * stringSize ) )
629 : {
630 0 : CPLFree(pszName);
631 0 : return NULL;
632 : }
633 7 : pszName[stringSize] = '\0';
634 :
635 : /* Read type */
636 7 : type = readUChar(pGTMFile);
637 :
638 : /* Read color */
639 7 : color = readInt(pGTMFile);
640 :
641 7 : Track* poTrack = new Track(pszName, type, color);
642 :
643 7 : CPLFree(pszName);
644 : /* Adjust actual Track offset */
645 7 : actualTrackOffset = VSIFTellL(pGTMFile) + 7;
646 7 : ++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 7 : 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 7 : if (start != 1)
662 : {
663 0 : delete poTrack;
664 0 : return NULL;
665 : }
666 7 : poTrack->addPoint(longitude, latitude, datetime, altitude);
667 :
668 28 : do
669 : {
670 : /* NOTE: Parameters are passed by reference */
671 28 : if ( !readTrackPoints(latitude, longitude, datetime, start, altitude) )
672 : {
673 0 : delete poTrack;
674 0 : return NULL;
675 : }
676 28 : if (start == 0)
677 23 : 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 7 : if (trackpointFetched < ntcks)
682 : {
683 5 : actualTrackpointOffset -= 25;
684 5 : --trackpointFetched;
685 : }
686 :
687 7 : return poTrack;
688 : }
689 :
690 :
691 :
692 : /************************************************************************/
693 : /* Private Methods Implementation */
694 : /************************************************************************/
695 4 : vsi_l_offset GTM::findFirstWaypointOffset()
696 : {
697 : /* Skip header and datum */
698 4 : if ( VSIFSeekL(pGTMFile, headerSize + DATUM_SIZE, SEEK_SET) != 0)
699 0 : return 0;
700 :
701 : /* Skip images */
702 : unsigned short stringSize;
703 6 : for (int i = 0; i < n_maps; ++i)
704 : {
705 : /* Read image name string size */
706 2 : stringSize = readUShort(pGTMFile);
707 :
708 : /* skip image name string */
709 2 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
710 0 : return 0;
711 :
712 : /* read image comment string size */
713 2 : stringSize = readUShort(pGTMFile);
714 :
715 : /* skip image comment string */
716 2 : if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
717 0 : return 0;
718 :
719 : /* skip the others image parameters */
720 2 : if ( VSIFSeekL(pGTMFile, 30, SEEK_CUR) != 0)
721 0 : return 0;
722 : }
723 4 : return VSIFTellL(pGTMFile);
724 : }
725 :
726 :
727 4 : vsi_l_offset GTM::findFirstTrackpointOffset()
728 : {
729 4 : 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 4 : if (VSIFSeekL(pGTMFile, firstWaypointOffset, SEEK_SET) != 0)
741 0 : return 0;
742 :
743 : unsigned short stringSize;
744 : int bSuccess;
745 : /* Skip waypoints */
746 11 : for (int i = 0; i < nwpts; ++i)
747 : {
748 : /* Seek file to the string size comment field */
749 7 : if (VSIFSeekL(pGTMFile, 26, SEEK_CUR) != 0)
750 0 : return 0;
751 : /* Read string comment size */
752 7 : stringSize = readUShort(pGTMFile, &bSuccess);
753 :
754 : /* Skip to the next Waypoint */
755 7 : 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 4 : if (nwpts != 0)
763 : {
764 21 : for (int i = 0; i < nwptstyles; ++i)
765 : {
766 : /* Seek file to the string size facename field */
767 17 : if (VSIFSeekL(pGTMFile, 4, SEEK_CUR) != 0)
768 0 : return 0;
769 :
770 : /* Read string facename size */
771 17 : stringSize = readUShort(pGTMFile, &bSuccess);
772 :
773 : /* Skip to the next Waypoint Style*/
774 17 : 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 4 : return VSIFTellL(pGTMFile);
780 : }
781 :
782 4 : vsi_l_offset GTM::findFirstTrackOffset()
783 : {
784 4 : 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 4 : return (vsi_l_offset) (firstTrackpointOffset + ntcks * 25);
793 : }
794 :
795 35 : bool GTM::readTrackPoints(double& latitude, double& longitude, GIntBig& datetime,
796 : unsigned char& start, float& altitude) {
797 : /* Point to the actual trackpoint offset */
798 35 : if ( VSIFSeekL(pGTMFile, actualTrackpointOffset, SEEK_SET) != 0)
799 0 : return FALSE;
800 :
801 : /* Read latitude */
802 35 : latitude = readDouble(pGTMFile);
803 :
804 : /* Read longitude */
805 35 : longitude = readDouble(pGTMFile);
806 :
807 : /* Read trackpoint date */
808 35 : datetime = readInt(pGTMFile);
809 35 : if (datetime != 0)
810 0 : datetime += GTM_EPOCH;
811 :
812 : /* Read start flag */
813 35 : if ( !readFile( &start, 1, 1 ) )
814 0 : return FALSE;
815 :
816 : /* Read altitude */
817 35 : altitude = readFloat(pGTMFile);
818 :
819 35 : ++trackpointFetched;
820 35 : if (trackpointFetched < ntcks)
821 : {
822 33 : actualTrackpointOffset += 8 + 8 + 4 + 1 + 4;
823 : }
824 35 : return TRUE;
825 : }
826 :
827 56 : bool GTM::readFile(void* pBuffer, size_t nSize, size_t nCount)
828 : {
829 : size_t nRead;
830 56 : nRead = VSIFReadL( pBuffer, nSize, nCount, pGTMFile );
831 56 : if (nRead <= 0)
832 : {
833 0 : VSIFCloseL( pGTMFile );
834 0 : pGTMFile = NULL;
835 0 : return FALSE;
836 : }
837 56 : return TRUE;
838 1947 : }
839 :
840 :
841 :
|