Kjørte mergesvn på alt under /trunk/src/gpstools/.
[gpstools.git] / gpst
blob73350b475d3c92a3c3fe58127622f28e20c5e91a
1 #!/usr/bin/perl -w
3 #=======================================================================
4 # $Id$
5 # Converts between various GPS formats
7 # Character set: UTF-8
8 # ©opyleft 2002– Øyvind A. Holm <sunny@sunbase.org>
9 # License: GNU General Public License version 2 or later, see end of
10 # file for legal stuff.
11 #=======================================================================
13 BEGIN {
14 our @version_array;
17 use strict;
18 use Getopt::Long;
19 use Time::Local qw { timegm_nocheck };
21 BEGIN {
22 push(@INC, "$ENV{'HOME'}/bin/src/gpstools");
23 our @version_array;
26 use GPST;
27 use GPSTdate;
28 use GPSTdebug;
29 use GPSTgeo;
30 use GPSTxml;
32 $| = 1;
34 our $Debug = 0;
36 our %Opt = (
37 # Initial values for command line arguments {{{
38 'chronology' => 0,
39 'comment-out-dups' => 0,
40 'create-breaks' => 0,
41 'debug' => 0,
42 'double-y-scale' => 0,
43 'epoch' => 0,
44 'fix' => 0,
45 'from-date' => "",
46 'help' => 0,
47 'inside' => 0,
48 'near' => "",
49 'output-format' => "gpsml",
50 'outside' => 0,
51 'pos1' => "",
52 'pos2' => "",
53 'require' => "",
54 'round' => "",
55 'save-to-file' => "\n", # \n = undefined, it’s banned in filenames anyway.
56 'short-date' => 0,
57 'skip-dups' => 0,
58 'strip-whitespace' => 0,
59 'undefined' => "",
60 'verbose' => 0,
61 'version' => 0,
62 # }}}
65 our $progname = $0;
66 $progname =~ s#^.*/(.*?)$#$1#;
68 my $rcs_id = '$Id$';
69 my $id_date = $rcs_id;
70 $id_date =~ s/^.*?\d+ (\d\d\d\d-.*?\d\d:\d\d:\d\d\S+).*/$1/;
72 push(@main::version_array, $rcs_id);
74 Getopt::Long::Configure("bundling");
75 GetOptions(
76 # Command line options {{{
77 "chronology" => \$Opt{'chronology'},
78 "comment-out-dups|u" => \$Opt{'comment-out-dups'},
79 "create-breaks|t" => \$Opt{'create-breaks'},
80 "debug" => \$Opt{'debug'},
81 "double-y-scale|y" => \$Opt{'double-y-scale'},
82 "epoch|e" => \$Opt{'epoch'},
83 "fix" => \$Opt{'fix'},
84 "from-date=s" => \$Opt{'from-date'},
85 "help|h" => \$Opt{'help'},
86 "inside" => \$Opt{'inside'},
87 "near" => \$Opt{'near'},
88 "output-format|o=s" => \$Opt{'output-format'},
89 "outside" => \$Opt{'outside'},
90 "pos1=s" => \$Opt{'pos1'},
91 "pos2=s" => \$Opt{'pos2'},
92 "require|r=s" => \$Opt{'require'},
93 "round|R=s" => \$Opt{'round'},
94 "save-to-file|S=s" => \$Opt{'save-to-file'},
95 "short-date|s" => \$Opt{'short-date'},
96 "skip-dups|d" => \$Opt{'skip-dups'},
97 "strip-whitespace|w" => \$Opt{'strip-whitespace'},
98 "undefined|n=s" => \$Opt{'undefined'},
99 "verbose|v+" => \$Opt{'verbose'},
100 "version" => \$Opt{'version'},
101 # }}}
102 ) || die("$progname: Option error. Use -h for help.\n");
104 my %Dat;
106 my $PAUSE_LIMIT = 2 * 60; # Antall sekunder mellom to punkter det må til før en move legges inn.
107 my $Udef = "?";
108 my $DIGIT = '[0-9\.\-\+]'; # Used in regexps
109 $GPST::Spc = $Opt{'strip-whitespace'} ? "" : " ";
110 my $Spc = $GPST::Spc; # FIXME
111 my $found_move = 0; # Settes til 1 hvis en /^# move$/ blir funnet.
112 my $first_time = 0;
113 my $last_time = 0;
114 my ($last_lon, $last_lat, $last_line) =
115 ( 1000, 1000, ""); # Vi kan jo teoretisk sett være i Greenwich eller på ekvator
116 my ($lat1, $lon1, $lat2, $lon2) =
117 (-1000, -1000, 1000, 1000);
119 our %Cmd = (
120 'gpsbabel' => '/usr/local/bin/gpsbabel',
123 my %Poscount = ();
125 if ($Opt{'output-format'} eq "pgtab") {
126 $Opt{'require'} .= "p";
128 my %Req = (
129 'ele' => ($Opt{'require'} =~ /e/) ? 1 : 0,
130 'position' => ($Opt{'require'} =~ /p/) ? 1 : 0,
131 'time' => ($Opt{'require'} =~ /t/) ? 1 : 0,
133 $Opt{'require'} =~ /[^ept]/
134 && die("$0: Unknown flag in --require (-r) value\n");
136 $Opt{'debug'} && ($Debug = 1);
137 $Opt{'help'} && usage(0);
138 $Opt{'version'} && print_version();
140 if ($Opt{'pos1'} =~ /^($DIGIT+),($DIGIT+)$/) {
141 $lat1 = $1;
142 $lon1 = $2;
144 if ($Opt{'pos2'} =~ /^($DIGIT+),($DIGIT+)$/) {
145 $lat2 = $1;
146 $lon2 = $2;
148 if ($lat1 > $lat2) {
149 my $Tmp = $lat1;
150 $lat1 = $lat2;
151 $lat2 = $Tmp;
153 if ($lon1 > $lon2) {
154 my $Tmp = $lon1;
155 $lon1 = $lon2;
156 $lon2 = $Tmp;
159 if ($Opt{'epoch'} && $Opt{'short-date'}) {
160 die("$progname: Cannot mix the --epoch (-e) and --short-date (-s) options\n");
163 if ($Opt{'inside'} && $Opt{'outside'}) {
164 die("$progname: Cannot mix the --inside and --outside options\n");
167 # To avoid printing out extra "/> at the start of svg output:
168 my $svg_start_thing = "";
170 my %Round = ();
172 if (defined($Opt{'round'})) {
173 my $R = $Opt{'round'};
174 $R =~ s/([a-z]+)=(\d+)/($Round{$1}=$2, "")/eg;
177 length($Opt{'undefined'}) && ($Udef = $Opt{'undefined'});
178 # Kunne vært et eget script på grunn av at det gjør sine helt egne
179 # greier, men like greit å samle det på en plass.
180 # FIXME: Fjerner ikke første duplikatentryen.
181 # FIXME: Se om det går å få flytta den inn i print_entry() så man
182 # slipper å ha to gptrans_conv’er i pipen.
183 # FIXME: Legg inn alle formatene.
184 if ($Opt{'comment-out-dups'}) {
185 # Comment out areas without reception {{{
186 my ($start_date, $end_date, $found_dup) = ("", "", 0);
187 my @Dup = ();
188 while (<>) {
189 if (
191 1\x20
192 (\S+)\x20 # Lat
193 (\S+)\x20 # Lon
194 (\S+)\x20 # Speed
195 (\S+)\x20 # Unknown
196 (\d\d)/(\d\d)/(\d\d\d\d)\x20 # Month/Day/Year — urgh
197 (\d\d):(\d\d):(\d\d) # Hour:Min:Sec
200 # {{{
201 my ($lat_val, $lon_val, $Speed, $Unkn,
202 $Month, $Day, $Year, $Hour, $Min, $Sec) =
203 ($1, $2, $3, $4,
204 $5, $6, $7, $8, $9, $10);
205 if (($lat_val eq $last_lat) && ($lon_val eq $last_lon)) {
206 unless ($found_dup) {
207 $start_date = "$Year$Month${Day}T$Hour$Min$Sec";
208 @Dup = ();
209 $found_dup = 1;
211 push(@Dup, "# $_");
212 $end_date = "$Year$Month${Day}T$Hour$Min$Sec";
213 } else {
214 if ($found_dup) {
215 print("# $start_date-$end_date: " .
216 "CO: No signal \x7B\x7B\x7B\n");
217 for (@Dup) {
218 print($_);
220 print("# $start_date-$end_date: " .
221 "CO: No signal \x7D\x7D\x7D\n# move\n$_");
222 $found_dup = 0;
223 } else {
224 print($_);
227 $last_lat = $lat_val;
228 $last_lon = $lon_val;
229 # }}}
230 } else {
231 if ($found_dup) {
232 push(@Dup, $_);
233 } else {
234 print($_);
238 if ($found_dup) {
239 print("# $start_date-$end_date: " .
240 "CO: No signal \x7B\x7B\x7B\n");
241 for (@Dup) {
242 print($_);
244 print("# $start_date-$end_date: " .
245 "CO: No signal \x7D\x7D\x7D\n# move\n");
246 $found_dup = 0;
248 exit(0);
249 # }}}
252 $Opt{'save-to-file'} eq "\n" && print_header(*STDOUT);
254 my @first_lines;
255 my $xml_data;
256 my $data_line = "";
257 our $curr_file = "";
259 my $from_stdin = scalar(@ARGV) ? 0 : 1;
261 $from_stdin && push(@ARGV, "-");
263 for $curr_file (@ARGV) {
264 # Scan through stdin or specified files and send every GPS entry to
265 # print_entry()
266 # {{{
267 print(STDERR "$progname: Opening \"$curr_file\" for read\n") if $Opt{'verbose'};
268 if (open(CurrFP, "<$curr_file")) {
269 # {{{
270 while (<CurrFP>) {
271 $data_line = $_;
272 %Dat = (
273 'year' => '', 'month' => '', 'day' => '',
274 'hour' => '', 'min' => '', 'sec' => '',
275 'epoch' => '',
276 'date-format' => '',
277 'lat' => '', 'lon' => '',
278 'ele' => '',
279 'desc' => '',
280 'error' => "",
281 'type' => 'tp',
284 $Opt{'epoch'} && ($Dat{'date-format'} = "epoch");
285 $Opt{'short-date'} && ($Dat{'date-format'} = "short");
287 if ($Opt{'save-to-file'} ne "\n") {
288 push(@first_lines, $_);
290 s/^# error // && ($Dat{'error'} = "error");
291 s/^# ?// && ($Dat{'error'} = "desc");
292 $xml_data = "";
293 if (m#^<(e?tp)\b(.*?)>(.*?)</(e?tp)>\s*$#) {
294 # gpsml — The main storage format {{{
295 my ($Elem, $Props, $Data) =
296 ( $1, $2, $3);
297 my $err_str = ($Props =~ /\berr="(.*?)"/) ? $1 : "error";
298 $Elem eq "etp" && ($Dat{'error'} = $err_str);
299 my $Time = "";
300 $Data =~ m#<time>(.*?)</time># && ($Time = $1);
301 $Time =~ s{
302 (\d\d\d\d)-?(\d\d)-?(\d\d)[T ](\d\d):?(\d\d):?([\d\.]+?)Z
304 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'},
305 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}) =
306 ( $1, $2, $3,
307 $4, $5, $6);
309 }ex;
310 $Data =~ m#<lat>($DIGIT*?)</lat># && ($Dat{'lat'} = $1);
311 $Data =~ m#<lon>($DIGIT*?)</lon># && ($Dat{'lon'} = $1);
312 $Data =~ m#<ele>($DIGIT*?)</ele># && ($Dat{'ele'} = $1);
313 $Data =~ m#<desc>(.*?)</desc># && ($Dat{'desc'} = $1);
314 print_entry(%Dat);
315 # }}}
316 } elsif (m#^<break\b.*?/>#) {
317 $found_move = 1;
318 } elsif (m#^<(title|pause)\b.*?>(.*?)</(title|pause)>#) {
319 $Dat{'type'} = $1;
320 $Dat{$1} = $2;
321 print_entry(%Dat);
322 } elsif (m#^<desc\b.*?>(.*$)#s) {
323 $Dat{'type'} = "desc";
324 my $Txt = $1;
325 until ($Txt =~ m#</desc>#s) {
326 $Txt .= <CurrFP>;
328 $Txt =~ s#^(.*)(</desc>.*$)#$1#s;
329 $Dat{'desc'} = $Txt;
330 print_entry(%Dat);
331 } elsif (/<gpx\b/) {
332 $xml_data = $_;
333 $xml_data .= join("", <CurrFP>);
334 if (!length($Opt{'output-format'})) {
335 $Opt{'output-format'} = "gpx";
336 print_header(*STDOUT);
338 read_xmlfile($xml_data);
339 last;
340 } elsif (/^move$/) {
341 $found_move = 1;
342 } elsif (m#^(\d+)\t($DIGIT+)\t($DIGIT+)\t($DIGIT)#) {
343 # CSV format, epoch style {{{
344 my ($ep_time, $lon_val, $lat_val, $Alt) =
345 ( $1, $2, $3, $4);
346 $Dat{'epoch'} = $ep_time;
347 ($Dat{'sec'}, $Dat{'min'}, $Dat{'hour'},
348 $Dat{'day'}, $Dat{'month'}, $Dat{'year'},
349 $Dat{'wday'}, $Dat{'yday'}) = gmtime($ep_time);
350 $Dat{'month'}++; # Urgh Ⅰ
351 $Dat{'year'} += 1900; # Urgh Ⅱ
352 print_entry(%Dat);
353 # }}}
354 } elsif (
356 (\d\d\d\d)-?(\d\d)-?(\d\d)[T\ ](\d\d):?(\d\d):?(\d\d)Z?\t
357 ($DIGIT+)\t($DIGIT+)\t($DIGIT)
360 # CSV format, human-readable date format {{{
361 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'},
362 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'},
363 $Dat{'lon'}, $Dat{'lat'}, $Dat{'ele'}) =
364 ($1, $2, $3,
365 $4, $5, $6,
366 $7, $8, $9);
367 print_entry(%Dat);
368 # }}}
369 } elsif (/^Trackpoint\t/) {
370 # Trackpoint\tN60.41630 E5.31675\t09.02.2006 20:24:37 (UTC)\t13.6 m\t\t93.9 m\t00:00:06\t56 kph\t123° true {{{
372 # Trackpoint\t
373 # N60.41630 E5.31675\t
374 # 09.02.2006 20:24:37 (UTC)\t
375 # 13.6 m\t
376 # \t
377 # 93.9 m\t
378 # 00:00:06\t
379 # 56 kph\t
380 # 123° true
381 my $Orig = $_;
382 $Orig =~ s/[\r\n]+$//;
383 my ($Marker_f, $Position_f, $Time_f, $Alt_f, $Depth_f,
384 $Leglength_f, $Legtime_f, $Legspeed_f, $Legcourse_f) =
385 split(/\t/, $Orig .
386 # Nødløsning for å unngå at variabler
387 # blir udefinert.
388 "\t\t\t\t\t\t\t\t\t\t"
390 D(join("",
391 "Position_f=\"$Position_f\" \x7B\x7B\x7B\n",
392 "Time_f=\"$Time_f\"\n",
393 "Alt_f=\"$Alt_f\"\n",
394 "Depth_f=\"$Depth_f\"\n",
395 "Leglength_f=\"$Leglength_f\"\n",
396 "Legtime_f=\"$Legtime_f\"\n",
397 "Legspeed_f=\"$Legspeed_f\"\n",
398 "Legcourse_f=\"$Legcourse_f\" \x7D\x7D\x7D\n",
400 my ($NS, $WE,
401 $Alt_unit,
402 $Leglength,
403 $Legtime_hour, $Legtime_min, $Legtime_sec,
404 $Legspeed, $Legspeed_unit,
405 $Legcourse
406 ) = ("", "", "", "", "", "", "", "", "", "", "", "", "",
407 "", "", "", "", "", "", "", "", "", "");
408 ($Position_f =~ /^(N|S)([\d\.]+) (W|E)([\d\.]+)/) &&
409 ($NS = $1, $Dat{'lat'} = $2, $WE = $3, $Dat{'lon'} = $4);
410 ($Time_f =~ /^(\d+)\.(\d+)\.(\d+) (\d+):(\d+):(\d+) \((.+?)\)/) &&
411 ($Dat{'day'} = $1, $Dat{'month'} = $2, $Dat{'year'} = $3,
412 $Dat{'hour'} = $4, $Dat{'min'} = $5, $Dat{'sec'} = $6);
413 ($Alt_f =~ /^($DIGIT+) (.*?)/) &&
414 ($Dat{'ele'} = $1, $Alt_unit = $2);
415 D("ele = \"$Dat{'ele'}\"");
416 ($NS eq "S") && ($Dat{'lat'} = 0-$Dat{'lat'});
417 ($WE eq "W") && ($Dat{'lon'} = 0-$Dat{'lon'});
418 # MapSource in win xp writes YYYY, but YY in win98se.
420 defined($Dat{'year'})
421 && $Dat{'year'} =~ /\d/
422 && $Dat{'year'} < 1900
423 ) && ($Dat{'year'} += 2000);
424 print_entry(%Dat);
425 # }}}
426 } elsif (/^Track\t(.*?)\t/) {
427 $Dat{'title'} = txt_to_xml($1);
428 $Dat{'type'} = "title";
429 $found_move = 1;
430 print_entry(%Dat);
431 } elsif (
434 (\d\d)/(\d\d)/(\d\d\d\d)\ (\d\d):(\d\d):(\d\d)\t
435 (.+)\xB0(.+)'(.+)"\t
436 (.+)\xB0(.+)'(.+)"
439 # T 09/01/2002 11:51:26 60°23'36.3" 5°19'35.9" {{{
440 my ($lat_d, $lat_m, $lat_s, $lon_d, $lon_m, $lon_s);
441 ($Dat{'month'}, $Dat{'day'}, $Dat{'year'},
442 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'},
443 $lat_d, $lat_m, $lat_s,
444 $lon_d, $lon_m, $lon_s) =
445 ($1, $2, $3,
446 $4, $5, $6,
447 $7, $8, $9,
448 $10, $11, $12);
449 my $Flat = defined($Round{'lat'}) ? ".$Round{'lat'}" : "";
450 my $Flon = defined($Round{'lon'}) ? ".$Round{'lon'}" : "";
451 $Dat{'lat'} = sprintf("%${Flat}f",
452 1.0*($lat_d+($lat_m/60)+($lat_s/3600)));
453 $Dat{'lon'} = sprintf("%${Flon}f",
454 1.0*$lon_d+($lon_m/60)+($lon_s/3600));
455 print_entry(%Dat);
456 # }}}
457 } elsif (
459 1\ (\S+)\ (\S+)\ (\S+)\ (\S+)\x20
460 (\d\d)/(\d\d)/(\d\d\d\d)\ (\d\d):(\d\d):(\d\d)
463 # 1 60.3938222 5.3238754 17.3 0 09/01/2002 14:18:23 {{{
464 ($Dat{'lat'}, $Dat{'lon'}, $Dat{'speed'},
465 $Dat{'unkn'},
466 $Dat{'month'}, $Dat{'day'}, $Dat{'year'},
467 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}) =
468 ($1, $2, $3,
470 $5, $6, $7,
471 $8, $9, $10);
472 print_entry(%Dat);
473 # }}}
474 } elsif (/^
475 # @020721221336N6048353E00701826S015-00001E4859N1673U0000 {{{
476 # Regexp {{{
477 (@) # @
478 (\d\d) # Year
479 (\d\d) # Month
480 (\d\d) # Day
481 (\d\d) # Hours
482 (\d\d) # Minutes
483 (\d\d) # Seconds
484 ([NS]) # N|S
485 (\d\d) # Latitude degree
486 (\d\d) # Latitude minute
487 (\d\d\d) # Latitude minute decimals
488 ([EW]) # E|W
489 (\d\d\d) # Longitude degree
490 (\d\d) # Longitude minute
491 (\d\d\d) # Longitude minute degree
492 (....) # Accurancy
493 (......) # Elevation
494 (...............)
495 # }}}
496 /x) {
497 my ($NS, $EW, $lat_deg, $lat_degmin, $lat_mindec, $lon_deg,
498 $lon_degmin, $lon_mindec);
499 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'}, $Dat{'hour'},
500 $Dat{'min'}, $Dat{'sec'}, $NS, $lat_deg,
501 $lat_degmin, $lat_mindec, $EW,
502 $lon_deg, $lon_degmin, $lon_mindec,
503 $Dat{'accur'}, $Dat{'ele'}, $Dat{'unknown'}) =
504 ($2+2000, $3, $4, $5,
505 $6, $7, $8, $9,
506 $10, $11, $12,
507 $13, $14, $15,
508 $16, $17, $18);
509 my $ep_time = timegm_nocheck(
510 $Dat{'sec'}, $Dat{'min'}, $Dat{'hour'},
511 $Dat{'day'}, $Dat{'month'}-1, $Dat{'year'}
513 $last_time = $ep_time;
514 my $Flat = defined($Round{'lat'}) ? ".$Round{'lat'}" : "";
515 my $Flon = defined($Round{'lon'}) ? ".$Round{'lon'}" : "";
516 my $tmp_lon = sprintf(
517 "%${Flon}f",
518 $lon_deg +
519 $lon_degmin/60 +
520 $lon_mindec/60000);
521 my $tmp_lat = sprintf("%${Flat}f",
522 $lat_deg +
523 $lat_degmin/60 +
524 $lat_mindec/60000);
525 ($NS eq "S") && ($tmp_lat = 0-$tmp_lat);
526 ($EW eq "W") && ($tmp_lon = 0-$tmp_lon);
527 $Dat{'lat'} = $tmp_lat;
528 $Dat{'lon'} = $tmp_lon;
529 print_entry(%Dat);
530 # }}}
531 } elsif (/^(@)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(_{42})/) {
532 # @020721221336__________________________________________ {{{
533 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'},
534 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}, $Dat{'rest'}) =
535 ($2+2000, $3, $4,
536 $5, $6, $7, $8);
537 $Dat{'error'} = "nosignal";
538 print_entry(%Dat);
539 # }}}
540 } elsif (/^xmaplog /) {
541 # NOP
542 } elsif (/^$/) {
543 ($Opt{'output-format'} eq "csv")
544 && ($Opt{'save-to-file'} eq "\n")
545 && print("\n");
546 } elsif (/^Pause: /) {
547 # NOP, is here to cope with old files I’ve lying around.
548 } elsif ($Dat{'error'} eq "desc") {
549 my $Comment = $_;
550 if (defined($Comment)) {
551 $Comment =~ s/^\s*(.*?)\s*$/$1/;
552 if ($Opt{'output-format'} eq "gpsml") {
553 $Dat{'desc'} = txt_to_xml($Comment);
554 $Dat{'type'} = "desc";
555 print_entry(%Dat);
558 } else {
559 $Opt{'verbose'} && warn("Line $.: Unknown: \"$_\"\n");
562 # }}}
563 } else {
564 warn("$progname: $curr_file: Cannot open file for read: $!\n");
566 # }}}
569 print_footer(*STDOUT);
571 exit(0);
573 sub read_xmlfile {
574 # {{{
575 my $Txt = join("", @_);
576 $Txt =~ s/<!--(.*?)-->//gs;
577 $Txt =~ s#(<gpx\b.*?>.*?</gpx>)#print_gpx($1)#gse;
578 # }}}
581 sub print_gpx {
582 # {{{
583 my $Orig = shift;
584 my $Str = $Orig;
585 # D("print_xml_gps(\"$Orig\")\n");
586 $Str =~ s/<!--(.*?)-->//gs;
587 my $fromdate_str = "";
588 if ($Opt{'from-date'}) {
589 $fromdate_str = "date >= '$Opt{'from-date'}' AND ";
591 if ($Opt{'output-format'} =~ /^(pgwtab|pgwupd)$/) {
592 # {{{
593 $Str =~
595 <wpt\b(.*?)>(.*?)</wpt>
598 my $attr_wpt = $1;
599 my $el_wpt = $2;
600 my ($Lat, $Lon, $Name, $Ele, $Type, $Time, $Cmt, $Desc, $Src, $Sym) =
601 ('\N', '\N', '\N', '\N', '\N', '\N', '\N', '\N', '\N', '\N');
603 $attr_wpt =~ /.*lat="($DIGIT+?)"/s &&
604 ($Lat = postgresql_copy_safe($1));
605 $attr_wpt =~ /.*lon="($DIGIT+?)"/s &&
606 ($Lon = postgresql_copy_safe($1));
607 $el_wpt =~ /.*<name\b(.*?)>(.*?)<\/name>/s &&
608 ($Name = postgresql_copy_safe(xml_to_txt($2)));
609 $el_wpt =~ /.*<ele\b(.*?)>(.*?)<\/ele>/s &&
610 ($Ele = postgresql_copy_safe(xml_to_txt($2)));
611 $el_wpt =~ /.*<type\b(.*?)>(.*?)<\/type>/s &&
612 ($Type = postgresql_copy_safe(xml_to_txt($2)));
613 $el_wpt =~ /.*<time\b(.*?)>(.*?)<\/time>/s &&
614 ($Time = postgresql_copy_safe(xml_to_txt($2)));
615 $el_wpt =~ /.*<cmt\b(.*?)>(.*?)<\/cmt>/s &&
616 ($Cmt = postgresql_copy_safe(xml_to_txt($2)));
617 $el_wpt =~ /.*<desc\b(.*?)>(.*?)<\/desc>/s &&
618 ($Desc = postgresql_copy_safe(xml_to_txt($2)));
619 $el_wpt =~ /.*<src\b(.*?)>(.*?)<\/src>/s &&
620 ($Src = postgresql_copy_safe(xml_to_txt($2)));
621 $el_wpt =~ /.*<sym\b(.*?)>(.*?)<\/sym>/s &&
622 ($Sym = postgresql_copy_safe(xml_to_txt($2)));
624 if ($Opt{'output-format'} eq "pgwtab") {
625 print(
626 join("\t",
627 "($Lat,$Lon)",
628 $Name,
629 $Ele,
630 $Type,
631 $Time,
632 $Cmt,
633 $Desc,
634 $Src,
635 $Sym
636 ) . "\n"
638 } elsif ($Opt{'output-format'} eq "pgwupd") {
639 $Name =~ s/'/''/gs;
640 print(join("\n",
641 "BEGIN;",
642 " UPDATE logg SET sted = clname(coor) " .
643 "WHERE $fromdate_str(point($Lat,$Lon) <-> coor) < 0.05;",
644 " UPDATE logg SET dist = cldist(coor) " .
645 "WHERE $fromdate_str(point($Lat,$Lon) <-> coor) < 0.05;",
646 "COMMIT;"
647 ) . "\n");
650 }gsex;
651 # }}}
652 } else {
653 # {{{
654 $Str =~
656 <trk\b(.*?)>(.*?)</trk>
659 my $el_trk = $2;
660 $el_trk =~
662 <name\b(.*?)>(.*?)</name>
664 my %tmp_dat = ();
665 $tmp_dat{'title'} = $2;
666 $tmp_dat{'type'} = "title";
667 $tmp_dat{'error'} = "";
668 print_entry(%tmp_dat);
670 }sex;
671 $el_trk =~
673 <trkseg\b(.*?)>(.*?)</trkseg>
676 my $el_trkseg = $2;
677 $el_trkseg =~
679 <trkpt\b(.*?)>(.*?)</trkpt>
682 my ($attr_trkpt, $el_trkpt) =
683 ( $1, $2);
684 %Dat = (
685 'year' => '', 'month' => '', 'day' => '',
686 'hour' => '', 'min' => '', 'sec' => '',
687 'epoch' => '',
688 'date-format' => '',
689 'lat' => '', 'lon' => '',
690 'ele' => '',
691 'desc' => '',
692 'error' => "",
693 'type' => 'tp',
695 ($attr_trkpt =~ /\blon="(.*?)"/) && ($Dat{'lon'} = $1);
696 ($attr_trkpt =~ /\blat="(.*?)"/) && ($Dat{'lat'} = $1);
697 ($el_trkpt =~ m#<ele\b.*?>(.*?)</ele>#) && ($Dat{'ele'} = $1);
698 if (
699 $el_trkpt =~
701 <time>(\d\d\d\d)-?(\d\d)-?(\d\d)T
702 (\d\d):?(\d\d):?([\d\.]+)Z</time>
705 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'},
706 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}) =
707 ($1, $2, $3, $4, $5, $6);
709 print_entry(%Dat);
711 }gsex;
712 $found_move = 1;
713 }gsex;
714 $found_move = 1;
715 }gsex;
716 # }}}
718 # }}}
721 sub print_header {
722 # {{{
723 local *OutFP = shift;
724 if ($Opt{'output-format'} eq "gpsml") {
725 print(OutFP join("",
726 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
727 "<gpsml>\n",
728 "<track>\n",
730 } elsif ($Opt{'output-format'} eq "gpstrans") {
731 print(OutFP "Format: DMS UTC Offset: 0.00 hrs " .
732 "Datum[100]: WGS 84\n");
733 } elsif ($Opt{'output-format'} eq "gpx") {
734 print(OutFP join("",
735 qq{<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n},
736 qq{<gpx\n},
737 qq{$Spc${Spc}version="1.1"\n},
738 qq{$Spc${Spc}creator="gpst - http://svn.sunbase.org/repos/utils/trunk/src/gpstools/"\n},
739 qq{$Spc${Spc}xmlns="http://www.topografix.com/GPX/1/1"\n},
740 qq{$Spc${Spc}xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n},
741 qq{$Spc${Spc}xsi:schemaLocation="http://www.topografix.com/GPX/1/1 },
742 qq{http://www.topografix.com/GPX/1/1/gpx.xsd"\n},
743 qq{>\n},
744 qq{$Spc$Spc<trk>\n},
745 qq{$Spc$Spc$Spc$Spc<trkseg>\n},
747 } elsif ($Opt{'output-format'} eq "ps") {
748 print(OutFP ps_header(532, 6034, 533, 6040));
749 print(OutFP "*u\n");
750 } elsif ($Opt{'output-format'} eq "svg") {
751 print(OutFP join("",
752 "<?xml version=\"1.0\" standalone=\"no\"?>\n",
753 "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
754 "$Spc$Spc\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
755 "<svg height=\"1000\" width=\"1000\" viewBox=\"23 70 2 2\"\n",
756 "$Spc${Spc}xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n",
757 "$Spc$Spc<title></title>\n",
758 "$Spc$Spc<desc></desc>\n",
761 # }}}
764 sub print_footer {
765 # Print footer {{{
766 local *OutFP = shift;
767 if ($Opt{'output-format'} eq "gpsml") {
768 print(OutFP join("",
769 "</track>\n",
770 "</gpsml>\n",
772 } elsif ($Opt{'output-format'} eq "gpx") {
773 print(OutFP join("",
774 "$Spc$Spc$Spc$Spc</trkseg>\n",
775 "$Spc$Spc</trk>\n",
776 "</gpx>\n",
778 } elsif ($Opt{'output-format'} eq "poscount") {
779 while (my ($l_name, $l_val) = each %Poscount) {
780 $l_name =~ /^(.+?),(.+?)$/
781 && print(OutFP "$1\t$2\t$l_val\n");
783 } elsif ($Opt{'output-format'} eq "ps") {
784 print(OutFP join("",
785 "*U\n",
786 "%%Trailer\n",
787 "%%EOF\n",
789 } elsif ($Opt{'output-format'} eq "svg") {
790 print(OutFP "\"/>\n</svg>\n");
792 # }}}
795 sub print_entry {
796 # Print a GPS entry with time, latitude, longitude and elevation in
797 # various formats
798 # {{{
799 my %Dat = @_;
800 defined($Dat{'desc'}) || ($Dat{'desc'} = "");
801 defined($Dat{'ele'}) || ($Dat{'ele'} = "");
802 defined($Dat{'lat'}) || ($Dat{'lat'} = "");
803 defined($Dat{'lon'}) || ($Dat{'lon'} = "");
804 defined($Dat{'year'}) || ($Dat{'year'} = "");
805 my $print_time = length($Dat{'year'}) ? 1 : 0;
806 my $print_pos = (length($Dat{'lat'}) && length($Dat{'lon'})) ? 1 : 0;
807 if (!$print_pos) {
808 $Dat{'lat'} = $Dat{'lon'} = "";
810 my $print_ele = length($Dat{'ele'}) ? 1 : 0;
811 my $print_desc = length($Dat{'desc'}) ? 1 : 0;
812 my $Line = "";
813 D("print_entry(\"" . join("\", \"", @_) . "\");");
814 my $ep_time;
816 if ($Opt{'near'} && $print_pos) {
817 $Line .= sprintf("%s ",
818 list_nearest_waypoints($Dat{'lat'}, $Dat{'lon'}));
821 if (length($Opt{'round'})) {
822 for my $Tmp (qw{ lat lon ele }) {
823 if (defined($Round{$Tmp}) && length($Dat{$Tmp})) {
824 D("Tmp = '$Tmp'");
825 ($Dat{$Tmp} = 1.0 * sprintf("%.$Round{$Tmp}f", $Dat{$Tmp}));
830 if ($Opt{'output-format'} eq "poscount") {
831 if (!length($Dat{'error'})) {
832 my $Name = "$Dat{'lon'},$Dat{'lat'}";
833 defined($Poscount{$Name}) || ($Poscount{$Name} = 0);
834 $Poscount{$Name}++;
836 return;
839 if ($print_time) {
840 $ep_time = timegm_nocheck(
841 $Dat{'sec'}, $Dat{'min'}, $Dat{'hour'},
842 $Dat{'day'}, $Dat{'month'} - 1, $Dat{'year'}
844 $Dat{'epoch'} = $ep_time;
845 $Dat{'year'} = sprintf("%04u", $Dat{'year'});
846 $Dat{'month'} = sprintf("%02u", $Dat{'month'});
847 $Dat{'day'} = sprintf("%02u", $Dat{'day'});
848 $Dat{'hour'} = sprintf("%02u", $Dat{'hour'});
849 $Dat{'min'} = sprintf("%02u", $Dat{'min'});
850 $Dat{'sec'} = sprintf("%02u", $Dat{'sec'});
851 if ($Opt{'chronology'}) {
852 if ($last_time > $ep_time && !length($Dat{'error'})) {
853 warn(sprintf(
854 "%s: $curr_file: \"%sZ\": Next date is %s in the past (%sZ)\n",
855 $progname, sec_to_string($last_time, "T"),
856 sec_to_readable($last_time-$ep_time),
857 sec_to_string($ep_time, "T")
859 # FIXME: Make --fix work with gpx.
860 if ($Opt{'fix'} && ($Opt{'output-format'} !~ /^gpx$/)) {
861 $Dat{'error'} = "chrono";
863 } elsif ($last_time == $ep_time && !length($Dat{'error'})) {
864 warn(sprintf(
865 "%s: $curr_file: \"%sZ\": Duplicated time\n",
866 $progname, sec_to_string($last_time, "T")
868 # FIXME: Make --fix work with gpx.
869 if ($Opt{'fix'} && ($Opt{'output-format'} !~ /^gpx$/)) {
870 $Dat{'error'} = "duptime";
874 } else {
875 $ep_time = 0;
876 $Dat{'year'} = 0;
877 $Dat{'month'} = 0;
878 $Dat{'day'} = 0;
879 $Dat{'hour'} = 0;
880 $Dat{'min'} = 0;
881 $Dat{'sec'} = 0;
884 if ($Opt{'save-to-file'} ne "\n") {
885 # {{{
886 $print_time || return;
887 my $base_name = "$Dat{'year'}$Dat{'month'}$Dat{'day'}T" .
888 "$Dat{'hour'}$Dat{'min'}$Dat{'sec'}Z" .
889 "$Opt{'save-to-file'}";
890 my $file_name = $base_name;
891 if (-e $file_name) {
892 for (my $a = 1; (-e $file_name) && ($a < 1000); $a++) {
893 $file_name = "$base_name.dup_$a";
895 if (-e $file_name) {
896 die("$progname: $base_name: File already exists, and ran " .
897 "out of attempts to create unique file name\n");
899 if ($Opt{'verbose'}) {
900 warn("$progname: $base_name: File already exists, using " .
901 "unique name \"$file_name\" instead\n");
904 if (open(ToFP, ">", $file_name)) {
905 print_header(*ToFP);
906 print(ToFP (
907 $from_stdin
908 ? @first_lines
909 : ()),
910 (length($xml_data)
911 ? $xml_data
912 : <>)
913 ) || die("$progname: $file_name: Cannot write to file: $!\n");
914 print_footer(*ToFP);
915 close(ToFP);
916 if ($Opt{'output-format'} eq "gpsml") {
917 printf("<include>%s</include>\n",
918 txt_to_xml($file_name));
919 } elsif ($Opt{'output-format'} eq "gpx") {
920 printf("<!-- Saved unconverted data to \"%s\" -->\n",
921 txt_to_xml($file_name));
922 } else {
923 print("$progname: Saved unconverted data to \"$file_name\"\n");
925 exit 0;
926 } else {
927 die("$progname: $file_name: Cannot create file: $!\n");
929 # }}}
932 my $pause_len = 0;
933 my $do_print = 1;
935 if ($Dat{'type'} eq "tp") {
936 # {{{
937 if ($Opt{'require'}) {
938 $Req{'time'} && !$print_time && return;
939 $Req{'position'} && !$print_pos && return;
940 $Req{'ele'} && !$print_ele && return;
943 if ($Opt{'inside'} || $Opt{'outside'}) {
944 if (
945 ($Dat{'lat'} < $lat1) ||
946 ($Dat{'lat'} > $lat2) ||
947 ($Dat{'lon'} < $lon1) ||
948 ($Dat{'lon'} > $lon2)
950 $Opt{'inside'} && return;
951 } else {
952 $Opt{'outside'} && return;
956 if ($Opt{'output-format'} eq "ps") {
957 $Dat{'lon'} *= 100;
958 $Dat{'lat'} *= 100;
961 if (
962 $Opt{'skip-dups'}
963 && ($Dat{'lon'} eq $last_lon)
964 && ($Dat{'lat'} eq $last_lat)
966 if ($Opt{'output-format'} eq 'gpsml') {
967 $Dat{'error'} = "dup";
968 } else {
969 $do_print = 0;
971 } else {
972 $do_print = 1;
975 if (
976 $Opt{'create-breaks'}
977 && $ep_time-$last_time > $PAUSE_LIMIT
978 && $last_time
980 $pause_len = $ep_time-$last_time;
981 D("pause_len set to '$pause_len'");
984 if ($pause_len) {
985 if ($Opt{'output-format'} eq "gpsml") {
986 $Line .= sprintf("<pause>%s</pause>\n",
987 sec_to_readable($ep_time-$last_time));
988 } elsif ($Opt{'output-format'} eq "clean") {
989 $pause_len && ($Line .= "\n");
990 } elsif ($Opt{'output-format'} eq "csv") {
991 $Line .= sprintf("# Pause: %s\n# move\n",
992 sec_to_readable($ep_time-$last_time));
993 } elsif ($Opt{'output-format'} eq "xgraph") {
994 $pause_len && ($Line .= "move ");
997 # }}}
1000 if ($do_print) {
1001 # Valid data was found, send to stdout {{{
1002 unless ($first_time) {
1003 $first_time = $ep_time;
1005 if ($Opt{'double-y-scale'} && length($Dat{'lat'})) {
1006 $Dat{'lat'} *= 2;
1008 if ($Opt{'output-format'} eq "gpsml") {
1009 if ($Dat{'type'} eq "tp") {
1010 $Dat{'format'} = "gpsml";
1011 $Line .= trackpoint(%Dat);
1012 } elsif ($Dat{'type'} =~ /^(pause|desc|title)$/) {
1013 $Line .= sprintf("<%s>%s</%s>\n",
1015 $Dat{$1},
1016 $1);
1018 } elsif ($Opt{'output-format'} eq "pgtab") {
1019 if ($Dat{'type'} eq "tp" && !length($Dat{'error'})) {
1020 $Dat{'format'} = "pgtab";
1021 $Line .= trackpoint(%Dat);
1023 } elsif ($Opt{'output-format'} eq "xgraph") {
1024 if ($print_pos && !length($Dat{'error'})) {
1025 $Dat{'format'} = "xgraph";
1026 $Line .= trackpoint(%Dat);
1028 } elsif($Opt{'output-format'} eq "gpstrans") {
1029 if ($print_pos && !length($Dat{'error'})) {
1030 $Dat{'format'} = "gpstrans";
1031 $Line .= trackpoint(%Dat);
1033 } elsif($Opt{'output-format'} eq "gpx") {
1034 if ($Dat{'type'} eq "tp") {
1035 $Dat{'format'} = "gpx";
1036 $Line .= trackpoint(%Dat);
1038 } elsif ($Opt{'output-format'} eq "clean") {
1039 if ($Dat{'type'} eq "tp" && !length($Dat{'error'})) {
1040 $Dat{'format'} = "clean";
1041 $Line .= trackpoint(%Dat);
1043 } elsif ($Opt{'output-format'} eq "ps") {
1044 $Line .= (
1045 $pause_len
1046 ? "f\n$Dat{'lon'} $Dat{'lat'} m\n"
1047 : "$Dat{'lon'} $Dat{'lat'} l\n"
1049 } elsif ($Opt{'output-format'} eq "svg") {
1050 $Line .= (
1051 ($last_lon == 1000) || $pause_len
1052 ? join("",
1053 "$svg_start_thing<path\n",
1054 " stroke=\"blue\"\n",
1055 " stroke-width=\"0.001\"\n",
1056 " fill=\"none\"\n",
1057 " d=\"\n",
1058 "M $Dat{'lon'} $Dat{'lat'}\n")
1059 : "L $Dat{'lon'} $Dat{'lat'}\n"
1061 } elsif ($Opt{'output-format'} eq "ygraph") {
1062 if (!length($Dat{'error'})) {
1063 my $Time = $print_time ? ($ep_time - $first_time) * 1 : 0;
1064 $Line .= "\"Time = $Time.0\n$Dat{'lon'} $Dat{'lat'}\n\n";
1066 } elsif ($Opt{'output-format'} eq "csv") {
1067 # {{{
1068 if (!length($Dat{'error'})) {
1069 $Dat{'format'} = "csv";
1070 $Line .= join("\t",
1071 $print_time
1072 ? $Opt{'epoch'}
1073 ? $ep_time
1074 : $Opt{'short-date'}
1075 ? "$Dat{'year'}$Dat{'month'}$Dat{'day'}T" .
1076 "$Dat{'hour'}$Dat{'min'}$Dat{'sec'}Z"
1077 : "$Dat{'year'}-$Dat{'month'}-$Dat{'day'}T" .
1078 "$Dat{'hour'}:$Dat{'min'}:$Dat{'sec'}Z"
1079 : "",
1080 $Dat{'lon'},
1081 $Dat{'lat'},
1082 $print_ele ? $Dat{'ele'} : "", # Elevation
1083 "\n"
1086 # }}}
1087 } elsif ($Opt{'output-format'} eq "pgwtab") {
1088 # FIXME: NOP at the moment.
1089 } else {
1090 die("$progname: \"$Opt{'output-format'}\": " .
1091 "Unknown output format\n");
1093 # }}}
1096 if (!$last_time && $Opt{'output-format'} eq "ps") {
1097 $Line .= "$Dat{'lon'} $Dat{'lat'} m\n";
1100 if ($do_print) {
1101 if ($found_move) {
1102 if ($Opt{'output-format'} eq "gpsml") {
1103 $Line = "<break/>\n$Line";
1105 (!$pause_len && ($Opt{'output-format'} eq "xgraph"))
1106 && ($Line .= "move $Line");
1107 ($Opt{'output-format'} eq "clean") && ($Line .= "\n");
1108 if ($Opt{'output-format'} eq "gpx") {
1109 $Line .= "$Spc$Spc$Spc$Spc</trkseg>\n" .
1110 "$Spc$Spc$Spc$Spc<trkseg>\n";
1112 $found_move = 0;
1114 print($Line);
1116 $print_time && ($last_time = $ep_time);
1117 if ($print_pos) {
1118 $last_lon = $Dat{'lon'};
1119 $last_lat = $Dat{'lat'};
1121 $last_line = $data_line;
1122 $svg_start_thing = "\"/>\n";
1123 # }}}
1126 sub ps_header {
1127 # Send a Postscript header to stdout {{{
1128 my ($bl_lon, $bl_lat, $br_lon, $br_lat) = @_;
1129 my $Date = sec_to_string(time);
1130 return(join("",
1131 "%!PS-Adobe-3.0 EPSF-3.0\n",
1132 "%%Creator: $rcs_id\n",
1133 "%%Title:\n",
1134 "%%CreationDate: $Date\n",
1135 "%%BoundingBox: $bl_lon $bl_lat $br_lon $br_lat\n",
1136 "%%DocumentData: Clean7Bit\n",
1137 "%%EndComments\n",
1138 "%%BeginProlog\n",
1139 "/bd { bind def } bind def\n",
1140 "/incompound false def\n",
1141 "/m { moveto } bd\n",
1142 "/l { lineto } bd\n",
1143 "/c { curveto } bd\n",
1144 "/F { incompound not {fill} if } bd\n",
1145 "/f { closepath F } bd\n",
1146 "/S { stroke } bd\n",
1147 "/*u { /incompound true def } bd\n",
1148 "/*U { /incompound false def f} bd\n",
1149 "/k { setcmykcolor } bd\n",
1150 "/K { k } bd\n",
1151 "%%EndProlog\n",
1152 "%%BeginSetup\n",
1153 "%%EndSetup\n",
1155 # }}}
1158 sub print_version {
1159 # Print program version {{{
1160 for (@main::version_array) {
1161 print("$_\n");
1163 exit(0);
1164 # }}}
1165 } # print_version()
1167 sub usage {
1168 # Send the help message to stdout {{{
1169 my $Retval = shift;
1171 print(<<END);
1173 $rcs_id
1175 Converts between various GPS formats.
1177 Usage: $progname [options] [file [files [...]]]
1178 $progname -S [file [files [...]]]
1179 $progname -u [file [files [...]]]
1181 Options:
1183 --chronology
1184 Check for broken chronology, warn about entries with an old
1185 timestamp.
1186 -d, --skip-dups
1187 Skip duplicated coordinates.
1188 -e, --epoch
1189 Use seconds since 1970-01-01 00:00:00 GMT as date format.
1190 --fix
1191 Comment out entries which is obviously wrong. Use together with
1192 --chronology to fix those kind of errors. Does not work with GPX
1193 output yet.
1194 --from-date x
1195 Used by the pgwupd format. Specifies from which date waypoints
1196 should be updated. No checks for valid date format here, let
1197 PostgreSQL take care of that. All variants it understands can be
1198 used here.
1199 -h, --help
1200 Show this help.
1201 --inside
1202 Print only trackpoints inside a rectangle specified by --pos1 and
1203 --pos2.
1204 -n, --undefined x
1205 Use x as undefined value. Default: "$Udef".
1206 --near
1207 Add names of the three closest waypoints to the trackpoint.
1208 Unfinished and experimental, needs gpsbabel, which is called from
1209 the program as "$Cmd{'gpsbabel'}".
1210 -o, --output-format x
1211 Use output format x:
1212 clean
1214 gpsml (Default)
1215 gpstrans
1216 gpx (Not complete)
1217 pgtab
1218 pgwtab
1219 pgwupd
1220 poscount
1221 ps (Unfinished)
1222 svg (Unfinished)
1223 xgraph
1224 ygraph
1225 --outside
1226 Print only trackpoints outside a rectangle specified by --pos1 and
1227 --pos2.
1228 --pos1 x
1229 --pos2 x
1230 Specifies one corner where x is in "lat,lon" format (decimal
1231 degrees, negative for west or south) of area rectangle used by the
1232 --inside and --outside options.
1233 -r, --require x
1234 Specify requirements for trackpoints to be written. x is a string
1235 with the following flags:
1237 Print only waypoints which have an elevation.
1239 Print only waypoints which have a position.
1241 Print only waypoints which have a timestamp.
1242 -R, --round x=y[,x2=y2[...]]
1243 Round trackpoint element x to y decimals. Example:
1244 --round lat=4,lon=5,ele=1
1245 -s, --short-date
1246 Use short date format.
1247 -S, --save-to-file x
1248 Save the unconverted data to a file with a filename starting with
1249 the timestamp of the first trackpoint. The parameter string x is
1250 added at the end of the filename. For the time being this option
1251 will ignore all other options. Note: If several files are specified
1252 on the command line, all data will be saved into only one file. This
1253 behaviour may change in the future.
1254 -t, --create-breaks
1255 Create breaks in track between points with a difference more than
1256 $PAUSE_LIMIT seconds.
1257 -u, --comment-out-dups
1258 Comment out following data with identical position values, only
1259 print first entry.
1260 -v, --verbose
1261 Increase level of verbosity. Can be repeated.
1262 --version
1263 Print version information.
1264 -w, --strip-whitespace
1265 Strip all unnecessary whitespace.
1266 -y, --double-y-scale
1267 Double Y scale (latitude) to get it right in gnuplot.
1268 --debug
1269 Print debugging messages.
1272 exit($Retval);
1273 # }}}
1274 } # usage()
1276 sub msg {
1277 # Print a status message to stderr based on verbosity level {{{
1278 my ($verbose_level, $Txt) = @_;
1280 if ($Opt{'verbose'} >= $verbose_level) {
1281 print(STDERR "$progname: $Txt\n");
1283 # }}}
1284 } # msg()
1286 __END__
1288 # Law talk {{{
1289 # Copyleft © Øyvind A. Holm <sunny@sunbase.org>
1291 # This program is free software; you can redistribute it and/or modify
1292 # it under the terms of the GNU General Public License as published by
1293 # the Free Software Foundation; either version 2 of the License, or (at
1294 # your option) any later version.
1296 # This program is distributed in the hope that it will be useful, but
1297 # WITHOUT ANY WARRANTY; without even the implied warranty of
1298 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1299 # See the GNU General Public License for more details.
1301 # You should have received a copy of the GNU General Public License
1302 # along with this program; if not, write to the Free Software
1303 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1304 # USA
1305 # }}}
1307 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :
1308 # End of file $Id$