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