gpsfold: Remove $Id$ at EOF.
[gpstools.git] / branches / gpst.gpsman-format / gpst
blob18c47742191a6a2d1e78f2d0bcc9a950d9de849a
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 (
541 # \t2003-12-02 10:06:17\tN50 05 31.2\tE14 26 10.4\t165.003417969
542 # (GPSMan)
543 # {{{
546 (\d\d\d\d)-(\d\d)-(\d\d)\ (\d\d):(\d\d):(\d\d)
548 (N|S)(\d+)\ (\d\d)\ (\d\d\.\d)
550 (W|E)(\d+)\ (\d\d)\ (\d\d\.\d)
552 ($DIGIT+)
554 /x) {
555 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'},
556 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}) =
557 ($1, $2, $3, $4, $5, $6);
558 my $NS = $7;
559 $Dat{'lat'} = dms_to_ddd($8, $9, $10);
560 my $WE = $11;
561 $Dat{'lon'} = dms_to_ddd($12, $13, $14);
562 $Dat{'ele'} = $15;
563 $NS eq "S" && ($Dat{'lat'} = 0 - $Dat{'lat'});
564 $WE eq "W" && ($Dat{'lon'} = 0 - $Dat{'lon'});
565 print_entry(%Dat);
566 # }}}
567 } elsif (/^!TS:$/) {
568 $found_move = 1;
569 print_entry(%Dat);
570 } elsif (/^!T:\t(.*?)\t/) {
571 $Dat{'title'} = $1;
572 $Dat{'type'} = "title";
573 print_entry(%Dat);
574 } elsif (/^xmaplog /) {
575 # NOP
576 } elsif (/^$/) {
577 ($Opt{'output-format'} eq "csv")
578 && ($Opt{'save-to-file'} eq "\n")
579 && print("\n");
580 } elsif (/^Pause: /) {
581 # NOP, is here to cope with old files I’ve lying around.
582 } elsif ($Dat{'error'} eq "desc") {
583 my $Comment = $_;
584 if (defined($Comment)) {
585 $Comment =~ s/^\s*(.*?)\s*$/$1/;
586 if ($Opt{'output-format'} eq "gpsml") {
587 $Dat{'desc'} = txt_to_xml($Comment);
588 $Dat{'type'} = "desc";
589 print_entry(%Dat);
592 } else {
593 $Opt{'verbose'} && warn("Line $.: Unknown: \"$_\"\n");
596 # }}}
597 } else {
598 warn("$progname: $curr_file: Cannot open file for read: $!\n");
600 # }}}
603 print_footer(*STDOUT);
605 exit(0);
607 sub read_xmlfile {
608 # {{{
609 my $Txt = join("", @_);
610 $Txt =~ s/<!--(.*?)-->//gs;
611 $Txt =~ s#(<gpx\b.*?>.*?</gpx>)#print_gpx($1)#gse;
612 # }}}
615 sub print_gpx {
616 # {{{
617 my $Orig = shift;
618 my $Str = $Orig;
619 # D("print_xml_gps(\"$Orig\")\n");
620 $Str =~ s/<!--(.*?)-->//gs;
621 my $fromdate_str = "";
622 if ($Opt{'from-date'}) {
623 $fromdate_str = "date >= '$Opt{'from-date'}' AND ";
625 if ($Opt{'output-format'} =~ /^(pgwtab|pgwupd)$/) {
626 # {{{
627 $Str =~
629 <wpt\b(.*?)>(.*?)</wpt>
632 my $attr_wpt = $1;
633 my $el_wpt = $2;
634 my ($Lat, $Lon, $Name, $Ele, $Type, $Time, $Cmt, $Desc, $Src, $Sym) =
635 ('\N', '\N', '\N', '\N', '\N', '\N', '\N', '\N', '\N', '\N');
637 $attr_wpt =~ /.*lat="($DIGIT+?)"/s &&
638 ($Lat = postgresql_copy_safe($1));
639 $attr_wpt =~ /.*lon="($DIGIT+?)"/s &&
640 ($Lon = postgresql_copy_safe($1));
641 $el_wpt =~ /.*<name\b(.*?)>(.*?)<\/name>/s &&
642 ($Name = postgresql_copy_safe(xml_to_txt($2)));
643 $el_wpt =~ /.*<ele\b(.*?)>(.*?)<\/ele>/s &&
644 ($Ele = postgresql_copy_safe(xml_to_txt($2)));
645 $el_wpt =~ /.*<type\b(.*?)>(.*?)<\/type>/s &&
646 ($Type = postgresql_copy_safe(xml_to_txt($2)));
647 $el_wpt =~ /.*<time\b(.*?)>(.*?)<\/time>/s &&
648 ($Time = postgresql_copy_safe(xml_to_txt($2)));
649 $el_wpt =~ /.*<cmt\b(.*?)>(.*?)<\/cmt>/s &&
650 ($Cmt = postgresql_copy_safe(xml_to_txt($2)));
651 $el_wpt =~ /.*<desc\b(.*?)>(.*?)<\/desc>/s &&
652 ($Desc = postgresql_copy_safe(xml_to_txt($2)));
653 $el_wpt =~ /.*<src\b(.*?)>(.*?)<\/src>/s &&
654 ($Src = postgresql_copy_safe(xml_to_txt($2)));
655 $el_wpt =~ /.*<sym\b(.*?)>(.*?)<\/sym>/s &&
656 ($Sym = postgresql_copy_safe(xml_to_txt($2)));
658 if ($Opt{'output-format'} eq "pgwtab") {
659 print(
660 join("\t",
661 "($Lat,$Lon)",
662 $Name,
663 $Ele,
664 $Type,
665 $Time,
666 $Cmt,
667 $Desc,
668 $Src,
669 $Sym
670 ) . "\n"
672 } elsif ($Opt{'output-format'} eq "pgwupd") {
673 $Name =~ s/'/''/gs;
674 print(join("\n",
675 "BEGIN;",
676 " UPDATE logg SET sted = clname(coor) " .
677 "WHERE $fromdate_str(point($Lat,$Lon) <-> coor) < 0.05;",
678 " UPDATE logg SET dist = cldist(coor) " .
679 "WHERE $fromdate_str(point($Lat,$Lon) <-> coor) < 0.05;",
680 "COMMIT;"
681 ) . "\n");
684 }gsex;
685 # }}}
686 } else {
687 # {{{
688 $Str =~
690 <trk\b(.*?)>(.*?)</trk>
693 my $el_trk = $2;
694 $el_trk =~
696 <name\b(.*?)>(.*?)</name>
698 my %tmp_dat = ();
699 $tmp_dat{'title'} = $2;
700 $tmp_dat{'type'} = "title";
701 $tmp_dat{'error'} = "";
702 print_entry(%tmp_dat);
704 }sex;
705 $el_trk =~
707 <trkseg\b(.*?)>(.*?)</trkseg>
710 my $el_trkseg = $2;
711 $el_trkseg =~
713 <trkpt\b(.*?)>(.*?)</trkpt>
716 my ($attr_trkpt, $el_trkpt) =
717 ( $1, $2);
718 %Dat = (
719 'year' => '', 'month' => '', 'day' => '',
720 'hour' => '', 'min' => '', 'sec' => '',
721 'epoch' => '',
722 'date-format' => '',
723 'lat' => '', 'lon' => '',
724 'ele' => '',
725 'desc' => '',
726 'error' => "",
727 'type' => 'tp',
729 ($attr_trkpt =~ /\blon="(.*?)"/) && ($Dat{'lon'} = $1);
730 ($attr_trkpt =~ /\blat="(.*?)"/) && ($Dat{'lat'} = $1);
731 ($el_trkpt =~ m#<ele\b.*?>(.*?)</ele>#) && ($Dat{'ele'} = $1);
732 if (
733 $el_trkpt =~
735 <time>(\d\d\d\d)-?(\d\d)-?(\d\d)T
736 (\d\d):?(\d\d):?([\d\.]+)Z</time>
739 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'},
740 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}) =
741 ($1, $2, $3, $4, $5, $6);
743 print_entry(%Dat);
745 }gsex;
746 $found_move = 1;
747 }gsex;
748 $found_move = 1;
749 }gsex;
750 # }}}
752 # }}}
755 sub print_header {
756 # {{{
757 local *OutFP = shift;
758 if ($Opt{'output-format'} eq "gpsml") {
759 print(OutFP join("",
760 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
761 "<gpsml>\n",
762 "<track>\n",
764 } elsif ($Opt{'output-format'} eq "gpstrans") {
765 print(OutFP "Format: DMS UTC Offset: 0.00 hrs " .
766 "Datum[100]: WGS 84\n");
767 } elsif ($Opt{'output-format'} eq "gpx") {
768 print(OutFP join("",
769 qq{<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n},
770 qq{<gpx\n},
771 qq{$Spc${Spc}version="1.1"\n},
772 qq{$Spc${Spc}creator="gpst - http://svn.sunbase.org/repos/utils/trunk/src/gpstools/"\n},
773 qq{$Spc${Spc}xmlns="http://www.topografix.com/GPX/1/1"\n},
774 qq{$Spc${Spc}xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n},
775 qq{$Spc${Spc}xsi:schemaLocation="http://www.topografix.com/GPX/1/1 },
776 qq{http://www.topografix.com/GPX/1/1/gpx.xsd"\n},
777 qq{>\n},
778 qq{$Spc$Spc<trk>\n},
779 qq{$Spc$Spc$Spc$Spc<trkseg>\n},
781 } elsif ($Opt{'output-format'} eq "ps") {
782 print(OutFP ps_header(532, 6034, 533, 6040));
783 print(OutFP "*u\n");
784 } elsif ($Opt{'output-format'} eq "svg") {
785 print(OutFP join("",
786 "<?xml version=\"1.0\" standalone=\"no\"?>\n",
787 "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
788 "$Spc$Spc\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
789 "<svg height=\"1000\" width=\"1000\" viewBox=\"23 70 2 2\"\n",
790 "$Spc${Spc}xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n",
791 "$Spc$Spc<title></title>\n",
792 "$Spc$Spc<desc></desc>\n",
795 # }}}
798 sub print_footer {
799 # Print footer {{{
800 local *OutFP = shift;
801 if ($Opt{'output-format'} eq "gpsml") {
802 print(OutFP join("",
803 "</track>\n",
804 "</gpsml>\n",
806 } elsif ($Opt{'output-format'} eq "gpx") {
807 print(OutFP join("",
808 "$Spc$Spc$Spc$Spc</trkseg>\n",
809 "$Spc$Spc</trk>\n",
810 "</gpx>\n",
812 } elsif ($Opt{'output-format'} eq "poscount") {
813 while (my ($l_name, $l_val) = each %Poscount) {
814 $l_name =~ /^(.+?),(.+?)$/
815 && print(OutFP "$1\t$2\t$l_val\n");
817 } elsif ($Opt{'output-format'} eq "ps") {
818 print(OutFP join("",
819 "*U\n",
820 "%%Trailer\n",
821 "%%EOF\n",
823 } elsif ($Opt{'output-format'} eq "svg") {
824 print(OutFP "\"/>\n</svg>\n");
826 # }}}
829 sub print_entry {
830 # Print a GPS entry with time, latitude, longitude and elevation in
831 # various formats
832 # {{{
833 my %Dat = @_;
834 defined($Dat{'desc'}) || ($Dat{'desc'} = "");
835 defined($Dat{'ele'}) || ($Dat{'ele'} = "");
836 defined($Dat{'lat'}) || ($Dat{'lat'} = "");
837 defined($Dat{'lon'}) || ($Dat{'lon'} = "");
838 defined($Dat{'year'}) || ($Dat{'year'} = "");
839 my $print_time = length($Dat{'year'}) ? 1 : 0;
840 my $print_pos = (length($Dat{'lat'}) && length($Dat{'lon'})) ? 1 : 0;
841 if (!$print_pos) {
842 $Dat{'lat'} = $Dat{'lon'} = "";
844 my $print_ele = length($Dat{'ele'}) ? 1 : 0;
845 my $print_desc = length($Dat{'desc'}) ? 1 : 0;
846 my $Line = "";
847 D("print_entry(\"" . join("\", \"", @_) . "\");");
848 my $ep_time;
850 if ($Opt{'near'} && $print_pos) {
851 $Line .= sprintf("%s ",
852 list_nearest_waypoints($Dat{'lat'}, $Dat{'lon'}));
855 if (length($Opt{'round'})) {
856 for my $Tmp (qw{ lat lon ele }) {
857 if (defined($Round{$Tmp}) && length($Dat{$Tmp})) {
858 D("Tmp = '$Tmp'");
859 ($Dat{$Tmp} = 1.0 * sprintf("%.$Round{$Tmp}f", $Dat{$Tmp}));
864 if ($Opt{'output-format'} eq "poscount") {
865 if (!length($Dat{'error'})) {
866 my $Name = "$Dat{'lon'},$Dat{'lat'}";
867 defined($Poscount{$Name}) || ($Poscount{$Name} = 0);
868 $Poscount{$Name}++;
870 return;
873 if ($print_time) {
874 $ep_time = timegm_nocheck(
875 $Dat{'sec'}, $Dat{'min'}, $Dat{'hour'},
876 $Dat{'day'}, $Dat{'month'} - 1, $Dat{'year'}
878 $Dat{'epoch'} = $ep_time;
879 $Dat{'year'} = sprintf("%04u", $Dat{'year'});
880 $Dat{'month'} = sprintf("%02u", $Dat{'month'});
881 $Dat{'day'} = sprintf("%02u", $Dat{'day'});
882 $Dat{'hour'} = sprintf("%02u", $Dat{'hour'});
883 $Dat{'min'} = sprintf("%02u", $Dat{'min'});
884 $Dat{'sec'} = sprintf("%02u", $Dat{'sec'});
885 if ($Opt{'chronology'}) {
886 if ($last_time > $ep_time && !length($Dat{'error'})) {
887 warn(sprintf(
888 "%s: $curr_file: \"%sZ\": Next date is %s in the past (%sZ)\n",
889 $progname, sec_to_string($last_time, "T"),
890 sec_to_readable($last_time-$ep_time),
891 sec_to_string($ep_time, "T")
893 # FIXME: Make --fix work with gpx.
894 if ($Opt{'fix'} && ($Opt{'output-format'} !~ /^gpx$/)) {
895 $Dat{'error'} = "chrono";
897 } elsif ($last_time == $ep_time && !length($Dat{'error'})) {
898 warn(sprintf(
899 "%s: $curr_file: \"%sZ\": Duplicated time\n",
900 $progname, sec_to_string($last_time, "T")
902 # FIXME: Make --fix work with gpx.
903 if ($Opt{'fix'} && ($Opt{'output-format'} !~ /^gpx$/)) {
904 $Dat{'error'} = "duptime";
908 } else {
909 $ep_time = 0;
910 $Dat{'year'} = 0;
911 $Dat{'month'} = 0;
912 $Dat{'day'} = 0;
913 $Dat{'hour'} = 0;
914 $Dat{'min'} = 0;
915 $Dat{'sec'} = 0;
918 if ($Opt{'save-to-file'} ne "\n") {
919 # {{{
920 $print_time || return;
921 my $base_name = "$Dat{'year'}$Dat{'month'}$Dat{'day'}T" .
922 "$Dat{'hour'}$Dat{'min'}$Dat{'sec'}Z" .
923 "$Opt{'save-to-file'}";
924 my $file_name = $base_name;
925 if (-e $file_name) {
926 for (my $a = 1; (-e $file_name) && ($a < 1000); $a++) {
927 $file_name = "$base_name.dup_$a";
929 if (-e $file_name) {
930 die("$progname: $base_name: File already exists, and ran " .
931 "out of attempts to create unique file name\n");
933 if ($Opt{'verbose'}) {
934 warn("$progname: $base_name: File already exists, using " .
935 "unique name \"$file_name\" instead\n");
938 if (open(ToFP, ">", $file_name)) {
939 print_header(*ToFP);
940 print(ToFP (
941 $from_stdin
942 ? @first_lines
943 : ()),
944 (length($xml_data)
945 ? $xml_data
946 : <>)
947 ) || die("$progname: $file_name: Cannot write to file: $!\n");
948 print_footer(*ToFP);
949 close(ToFP);
950 if ($Opt{'output-format'} eq "gpsml") {
951 printf("<include>%s</include>\n",
952 txt_to_xml($file_name));
953 } elsif ($Opt{'output-format'} eq "gpx") {
954 printf("<!-- Saved unconverted data to \"%s\" -->\n",
955 txt_to_xml($file_name));
956 } else {
957 print("$progname: Saved unconverted data to \"$file_name\"\n");
959 exit 0;
960 } else {
961 die("$progname: $file_name: Cannot create file: $!\n");
963 # }}}
966 my $pause_len = 0;
967 my $do_print = 1;
969 if ($Dat{'type'} eq "tp") {
970 # {{{
971 if ($Opt{'require'}) {
972 $Req{'time'} && !$print_time && return;
973 $Req{'position'} && !$print_pos && return;
974 $Req{'ele'} && !$print_ele && return;
977 if ($Opt{'inside'} || $Opt{'outside'}) {
978 if (
979 ($Dat{'lat'} < $lat1) ||
980 ($Dat{'lat'} > $lat2) ||
981 ($Dat{'lon'} < $lon1) ||
982 ($Dat{'lon'} > $lon2)
984 $Opt{'inside'} && return;
985 } else {
986 $Opt{'outside'} && return;
990 if ($Opt{'output-format'} eq "ps") {
991 $Dat{'lon'} *= 100;
992 $Dat{'lat'} *= 100;
995 if (
996 $Opt{'skip-dups'}
997 && ($Dat{'lon'} eq $last_lon)
998 && ($Dat{'lat'} eq $last_lat)
1000 if ($Opt{'output-format'} eq 'gpsml') {
1001 $Dat{'error'} = "dup";
1002 } else {
1003 $do_print = 0;
1005 } else {
1006 $do_print = 1;
1009 if (
1010 $Opt{'create-breaks'}
1011 && $ep_time-$last_time > $PAUSE_LIMIT
1012 && $last_time
1014 $pause_len = $ep_time-$last_time;
1015 D("pause_len set to '$pause_len'");
1018 if ($pause_len) {
1019 if ($Opt{'output-format'} eq "gpsml") {
1020 $Line .= sprintf("<pause>%s</pause>\n",
1021 sec_to_readable($ep_time-$last_time));
1022 } elsif ($Opt{'output-format'} eq "clean") {
1023 $pause_len && ($Line .= "\n");
1024 } elsif ($Opt{'output-format'} eq "csv") {
1025 $Line .= sprintf("# Pause: %s\n# move\n",
1026 sec_to_readable($ep_time-$last_time));
1027 } elsif ($Opt{'output-format'} eq "xgraph") {
1028 $pause_len && ($Line .= "move ");
1031 # }}}
1034 if ($do_print) {
1035 # Valid data was found, send to stdout {{{
1036 unless ($first_time) {
1037 $first_time = $ep_time;
1039 if ($Opt{'double-y-scale'} && length($Dat{'lat'})) {
1040 $Dat{'lat'} *= 2;
1042 if ($Opt{'output-format'} eq "gpsml") {
1043 if ($Dat{'type'} eq "tp") {
1044 $Dat{'format'} = "gpsml";
1045 $Line .= trackpoint(%Dat);
1046 } elsif ($Dat{'type'} =~ /^(pause|desc|title)$/) {
1047 $Line .= sprintf("<%s>%s</%s>\n",
1049 $Dat{$1},
1050 $1);
1052 } elsif ($Opt{'output-format'} eq "pgtab") {
1053 if ($Dat{'type'} eq "tp" && !length($Dat{'error'})) {
1054 $Dat{'format'} = "pgtab";
1055 $Line .= trackpoint(%Dat);
1057 } elsif ($Opt{'output-format'} eq "xgraph") {
1058 if ($print_pos && !length($Dat{'error'})) {
1059 $Dat{'format'} = "xgraph";
1060 $Line .= trackpoint(%Dat);
1062 } elsif($Opt{'output-format'} eq "gpstrans") {
1063 if ($print_pos && !length($Dat{'error'})) {
1064 $Dat{'format'} = "gpstrans";
1065 $Line .= trackpoint(%Dat);
1067 } elsif($Opt{'output-format'} eq "gpx") {
1068 $Dat{'format'} = "gpx";
1069 if ($Dat{'type'} =~ /^(tp|title)$/) {
1070 $Line .= trackpoint(%Dat);
1072 } elsif ($Opt{'output-format'} eq "clean") {
1073 if ($Dat{'type'} eq "tp" && !length($Dat{'error'})) {
1074 $Dat{'format'} = "clean";
1075 $Line .= trackpoint(%Dat);
1077 } elsif ($Opt{'output-format'} eq "ps") {
1078 $Line .= (
1079 $pause_len
1080 ? "f\n$Dat{'lon'} $Dat{'lat'} m\n"
1081 : "$Dat{'lon'} $Dat{'lat'} l\n"
1083 } elsif ($Opt{'output-format'} eq "svg") {
1084 $Line .= (
1085 ($last_lon == 1000) || $pause_len
1086 ? join("",
1087 "$svg_start_thing<path\n",
1088 " stroke=\"blue\"\n",
1089 " stroke-width=\"0.001\"\n",
1090 " fill=\"none\"\n",
1091 " d=\"\n",
1092 "M $Dat{'lon'} $Dat{'lat'}\n")
1093 : "L $Dat{'lon'} $Dat{'lat'}\n"
1095 } elsif ($Opt{'output-format'} eq "ygraph") {
1096 if (!length($Dat{'error'})) {
1097 my $Time = $print_time ? ($ep_time - $first_time) * 1 : 0;
1098 $Line .= "\"Time = $Time.0\n$Dat{'lon'} $Dat{'lat'}\n\n";
1100 } elsif ($Opt{'output-format'} eq "csv") {
1101 # {{{
1102 if (!length($Dat{'error'})) {
1103 $Dat{'format'} = "csv";
1104 $Line .= join("\t",
1105 $print_time
1106 ? $Opt{'epoch'}
1107 ? $ep_time
1108 : $Opt{'short-date'}
1109 ? "$Dat{'year'}$Dat{'month'}$Dat{'day'}T" .
1110 "$Dat{'hour'}$Dat{'min'}$Dat{'sec'}Z"
1111 : "$Dat{'year'}-$Dat{'month'}-$Dat{'day'}T" .
1112 "$Dat{'hour'}:$Dat{'min'}:$Dat{'sec'}Z"
1113 : "",
1114 $Dat{'lon'},
1115 $Dat{'lat'},
1116 $print_ele ? $Dat{'ele'} : "", # Elevation
1117 "\n"
1120 # }}}
1121 } elsif ($Opt{'output-format'} eq "pgwtab") {
1122 # FIXME: NOP at the moment.
1123 } else {
1124 die("$progname: \"$Opt{'output-format'}\": " .
1125 "Unknown output format\n");
1127 # }}}
1130 if (!$last_time && $Opt{'output-format'} eq "ps") {
1131 $Line .= "$Dat{'lon'} $Dat{'lat'} m\n";
1134 if ($do_print) {
1135 if ($found_move) {
1136 if ($Opt{'output-format'} eq "gpsml") {
1137 $Line = "<break/>\n$Line";
1139 (!$pause_len && ($Opt{'output-format'} eq "xgraph"))
1140 && ($Line .= "move $Line");
1141 ($Opt{'output-format'} eq "clean") && ($Line .= "\n");
1142 if ($Opt{'output-format'} eq "gpx") {
1143 $Line .= "$Spc$Spc$Spc$Spc</trkseg>\n" .
1144 "$Spc$Spc$Spc$Spc<trkseg>\n";
1146 $found_move = 0;
1148 print($Line);
1150 $print_time && ($last_time = $ep_time);
1151 if ($print_pos) {
1152 $last_lon = $Dat{'lon'};
1153 $last_lat = $Dat{'lat'};
1155 $last_line = $data_line;
1156 $svg_start_thing = "\"/>\n";
1157 # }}}
1160 sub ps_header {
1161 # Send a Postscript header to stdout {{{
1162 my ($bl_lon, $bl_lat, $br_lon, $br_lat) = @_;
1163 my $Date = sec_to_string(time);
1164 return(join("",
1165 "%!PS-Adobe-3.0 EPSF-3.0\n",
1166 "%%Creator: $rcs_id\n",
1167 "%%Title:\n",
1168 "%%CreationDate: $Date\n",
1169 "%%BoundingBox: $bl_lon $bl_lat $br_lon $br_lat\n",
1170 "%%DocumentData: Clean7Bit\n",
1171 "%%EndComments\n",
1172 "%%BeginProlog\n",
1173 "/bd { bind def } bind def\n",
1174 "/incompound false def\n",
1175 "/m { moveto } bd\n",
1176 "/l { lineto } bd\n",
1177 "/c { curveto } bd\n",
1178 "/F { incompound not {fill} if } bd\n",
1179 "/f { closepath F } bd\n",
1180 "/S { stroke } bd\n",
1181 "/*u { /incompound true def } bd\n",
1182 "/*U { /incompound false def f} bd\n",
1183 "/k { setcmykcolor } bd\n",
1184 "/K { k } bd\n",
1185 "%%EndProlog\n",
1186 "%%BeginSetup\n",
1187 "%%EndSetup\n",
1189 # }}}
1192 sub print_version {
1193 # Print program version {{{
1194 for (@main::version_array) {
1195 print("$_\n");
1197 exit(0);
1198 # }}}
1199 } # print_version()
1201 sub usage {
1202 # Send the help message to stdout {{{
1203 my $Retval = shift;
1205 print(<<END);
1207 $rcs_id
1209 Converts between various GPS formats.
1211 Usage: $progname [options] [file [files [...]]]
1212 $progname -S [file [files [...]]]
1213 $progname -u [file [files [...]]]
1215 Options:
1217 --chronology
1218 Check for broken chronology, warn about entries with an old
1219 timestamp.
1220 -d, --skip-dups
1221 Skip duplicated coordinates.
1222 -e, --epoch
1223 Use seconds since 1970-01-01 00:00:00 GMT as date format.
1224 --fix
1225 Comment out entries which is obviously wrong. Use together with
1226 --chronology to fix those kind of errors. Does not work with GPX
1227 output yet.
1228 --from-date x
1229 Used by the pgwupd format. Specifies from which date waypoints
1230 should be updated. No checks for valid date format here, let
1231 PostgreSQL take care of that. All variants it understands can be
1232 used here.
1233 -h, --help
1234 Show this help.
1235 --inside
1236 Print only trackpoints inside a rectangle specified by --pos1 and
1237 --pos2.
1238 -n, --undefined x
1239 Use x as undefined value. Default: "$Udef".
1240 --near
1241 Add names of the three closest waypoints to the trackpoint.
1242 Unfinished and experimental, needs gpsbabel, which is called from
1243 the program as "$Cmd{'gpsbabel'}".
1244 -o, --output-format x
1245 Use output format x:
1246 clean
1248 gpsml (Default)
1249 gpstrans
1250 gpx (Not complete)
1251 pgtab
1252 pgwtab
1253 pgwupd
1254 poscount
1255 ps (Unfinished)
1256 svg (Unfinished)
1257 xgraph
1258 ygraph
1259 --outside
1260 Print only trackpoints outside a rectangle specified by --pos1 and
1261 --pos2.
1262 --pos1 x
1263 --pos2 x
1264 Specifies one corner where x is in "lat,lon" format (decimal
1265 degrees, negative for west or south) of area rectangle used by the
1266 --inside and --outside options.
1267 -r, --require x
1268 Specify requirements for trackpoints to be written. x is a string
1269 with the following flags:
1271 Print only waypoints which have an elevation.
1273 Print only waypoints which have a position.
1275 Print only waypoints which have a timestamp.
1276 -R, --round x=y[,x2=y2[...]]
1277 Round trackpoint element x to y decimals. Example:
1278 --round lat=4,lon=5,ele=1
1279 -s, --short-date
1280 Use short date format.
1281 -S, --save-to-file x
1282 Save the unconverted data to a file with a filename starting with
1283 the timestamp of the first trackpoint. The parameter string x is
1284 added at the end of the filename. For the time being this option
1285 will ignore all other options. Note: If several files are specified
1286 on the command line, all data will be saved into only one file. This
1287 behaviour may change in the future.
1288 -t, --create-breaks
1289 Create breaks in track between points with a difference more than
1290 $PAUSE_LIMIT seconds.
1291 -u, --comment-out-dups
1292 Comment out following data with identical position values, only
1293 print first entry.
1294 -v, --verbose
1295 Increase level of verbosity. Can be repeated.
1296 --version
1297 Print version information.
1298 -w, --strip-whitespace
1299 Strip all unnecessary whitespace.
1300 -y, --double-y-scale
1301 Double Y scale (latitude) to get it right in gnuplot.
1302 --debug
1303 Print debugging messages.
1306 exit($Retval);
1307 # }}}
1308 } # usage()
1310 sub msg {
1311 # Print a status message to stderr based on verbosity level {{{
1312 my ($verbose_level, $Txt) = @_;
1314 if ($Opt{'verbose'} >= $verbose_level) {
1315 print(STDERR "$progname: $Txt\n");
1317 # }}}
1318 } # msg()
1320 __END__
1322 # Law talk {{{
1323 # Copyleft © Øyvind A. Holm <sunny@sunbase.org>
1325 # This program is free software; you can redistribute it and/or modify
1326 # it under the terms of the GNU General Public License as published by
1327 # the Free Software Foundation; either version 2 of the License, or (at
1328 # your option) any later version.
1330 # This program is distributed in the hope that it will be useful, but
1331 # WITHOUT ANY WARRANTY; without even the implied warranty of
1332 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1333 # See the GNU General Public License for more details.
1335 # You should have received a copy of the GNU General Public License
1336 # along with this program; if not, write to the Free Software
1337 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1338 # USA
1339 # }}}
1341 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :
1342 # End of file $Id$