gpsfold: Remove $Id$ at EOF.
[gpstools.git] / branches / gpst.gpsman-format / Patch / gpst-u-integrate
blob6b14beb85549d74e2eb6d46db7d782d70d306575
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 $| = 1;
18 our $Debug = 0;
20 our %Opt = (
21 # Initial values for command line arguments {{{
22 'chronology' => 0,
23 'comment-out-dups' => 0,
24 'create-breaks' => 0,
25 'debug' => 0,
26 'double-y-scale' => 0,
27 'epoch' => 0,
28 'fix' => 0,
29 'help' => 0,
30 'inside' => 0,
31 'near' => "",
32 'output-format' => "gpsml",
33 'outside' => 0,
34 'pos1' => "",
35 'pos2' => "",
36 'print-comments' => 0,
37 'require' => "",
38 'save-to-file' => "\n", # \n = undefined, it’s banned in filenames anyway.
39 'short-date' => 0,
40 'skip-dups' => 0,
41 'strip-whitespace' => 0,
42 'undefined' => "",
43 'use-comma' => 0,
44 'version' => 0,
45 # }}}
48 our $progname = $0;
49 $progname =~ s#^.*/(.*?)$#$1#;
51 my $rcs_id = '$Id$';
52 my $id_date = $rcs_id;
53 $id_date =~ s/^.*?\d+ (\d\d\d\d-.*?\d\d:\d\d:\d\d\S+).*/$1/;
55 Getopt::Long::Configure("bundling");
56 GetOptions(
57 # Command line options {{{
58 "chronology" => \$Opt{'chronology'},
59 "comment-out-dups|u" => \$Opt{'comment-out-dups'},
60 "create-breaks|t" => \$Opt{'create-breaks'},
61 "debug" => \$Opt{'debug'},
62 "double-y-scale|y" => \$Opt{'double-y-scale'},
63 "epoch|e" => \$Opt{'epoch'},
64 "fix" => \$Opt{'fix'},
65 "help|h" => \$Opt{'help'},
66 "inside" => \$Opt{'inside'},
67 "near" => \$Opt{'near'},
68 "output-format|o=s" => \$Opt{'output-format'},
69 "outside" => \$Opt{'outside'},
70 "pos1=s" => \$Opt{'pos1'},
71 "pos2=s" => \$Opt{'pos2'},
72 "print-comments|C" => \$Opt{'print-comments'},
73 "require|r=s" => \$Opt{'require'},
74 "save-to-file|S=s" => \$Opt{'save-to-file'},
75 "short-date|s" => \$Opt{'short-date'},
76 "skip-dups|d" => \$Opt{'skip-dups'},
77 "strip-whitespace|w" => \$Opt{'strip-whitespace'},
78 "undefined|n=s" => \$Opt{'undefined'},
79 "use-comma|c" => \$Opt{'use-comma'},
80 "verbose|v" => \$Opt{'verbose'},
81 "version" => \$Opt{'version'},
82 # }}}
83 ) || die("$progname: Option error. Use -h for help.\n");
85 my %Dat;
87 my $PAUSE_LIMIT = 2 * 60; # Antall sekunder mellom to punkter det må til før en move legges inn.
88 my $Des = $Opt{'use-comma'} ? "," : ".";
89 my $Udef = "?";
90 my $DIGIT = '[0-9\.\-\+]'; # Used in regexps
91 my $Spc = $Opt{'strip-whitespace'} ? "" : " ";
92 my $in_dupskip = 0; # Er 1 hvis vi holder på med ignorering av duplikater
93 my $found_move = 0; # Settes til 1 hvis en /^# move$/ blir funnet.
94 my $first_time = 0;
95 my $last_time = 0;
96 my ($last_lon, $last_lat, $last_ele, $last_line) =
97 ( 1000, 1000, 100000, ""); # Vi kan jo teoretisk sett være i Greenwich eller på ekvator
98 my ($lat1, $lon1, $lat2, $lon2) =
99 (-1000, -1000, 1000, 1000);
100 my ($start_date, $end_date, $found_dup) =
101 ( "", "", 0);
102 my @Dup = ();
104 my %Poscount = ();
106 my %Req = (
107 'altitude' => ($Opt{'require'} =~ /a/) ? 1 : 0,
108 'time' => ($Opt{'require'} =~ /t/) ? 1 : 0
110 $Opt{'require'} =~ /[^at]/ && die("$0: Unknown flag in --require (-r) value\n");
112 $Opt{'debug'} && ($Debug = 1);
113 $Opt{'help'} && usage(0);
114 $Opt{'version'} && print_version();
116 if ($Opt{'pos1'} =~ /^($DIGIT+),($DIGIT+)$/) {
117 $lat1 = $1;
118 $lon1 = $2;
120 if ($Opt{'pos2'} =~ /^($DIGIT+),($DIGIT+)$/) {
121 $lat2 = $1;
122 $lon2 = $2;
124 if ($lat1 > $lat2) {
125 my $Tmp = $lat1;
126 $lat1 = $lat2;
127 $lat2 = $Tmp;
129 if ($lon1 > $lon2) {
130 my $Tmp = $lon1;
131 $lon1 = $lon2;
132 $lon2 = $Tmp;
135 if ($Opt{'inside'} && $Opt{'outside'}) {
136 die("$progname: Cannot mix the --inside and --outside options\n");
139 my $waypoint_file = "/home/sunny/gps/waypoints.gpx";
141 # To avoid printing out extra "/> at the start of svg output:
142 my $svg_start_thing = "";
144 length($Opt{'undefined'}) && ($Udef = $Opt{'undefined'});
145 # Kunne vært et eget script på grunn av at det gjør sine helt egne
146 # greier, men like greit å samle det på en plass.
147 # FIXME: Fjerner ikke første duplikatentryen.
148 # FIXME: Se om det går å få flytta den inn i print_entry() så man
149 # slipper å ha to gptrans_conv’er i pipen.
150 # FIXME: Legg inn alle formatene.
151 if (0 && $Opt{'comment-out-dups'}) {
152 # Comment out areas without reception {{{
153 while (<>) {
154 if (m#^1 (\S+) (\S+) (\S+) (\S+) (\d\d)/(\d\d)/(\d\d\d\d) (\d\d):(\d\d):(\d\d)#) {
155 # {{{
156 my ($lat_val, $lon_val, $Speed, $Unkn, $Month, $Day, $Year, $Hour, $Min, $Sec) =
157 ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
158 # }}}
159 } else {
160 if ($found_dup) {
161 push(@Dup, $_);
162 } else {
163 print($_);
167 if ($found_dup) {
168 print("# $start_date-$end_date: CO: No signal \x7B\x7B\x7B\n");
169 for (@Dup) {
170 print($_);
172 print("# $start_date-$end_date: CO: No signal \x7D\x7D\x7D\n# move\n");
173 $found_dup = 0;
175 exit(0);
176 # }}}
179 $Opt{'save-to-file'} eq "\n" && print_header(*STDOUT);
181 my @first_lines;
182 my $xml_data;
183 my $data_line = "";
184 my $curr_file = "";
186 my $from_stdin = scalar(@ARGV) ? 0 : 1;
188 $from_stdin && push(@ARGV, "-");
190 for $curr_file (@ARGV) {
191 # Scan through stdin or specified files and send every GPS entry to
192 # print_entry()
193 # {{{
194 D("Opening \"$curr_file\" for read");
195 if (open(CurrFP, "<$curr_file")) {
196 # {{{
197 while (<CurrFP>) {
198 $data_line = $_;
199 %Dat = (
200 'year' => '', 'month' => '', 'day' => '',
201 'hour' => '', 'min' => '', 'sec' => '',
202 'lat' => '', 'lon' => '',
203 'ele' => '',
204 'desc' => '',
205 'error' => 0,
206 'type' => 'tp',
209 if ($Opt{'save-to-file'} ne "\n") {
210 push(@first_lines, $_);
211 $_ =~ s/^# ?//; # Also read commented-out lines.
213 $xml_data = "";
214 if (m#^<(e?tp)\b.*?>(.*?)</(e?tp)>$#) {
215 # gpsml — The main storage format {{{
216 my ($Elem, $Data) =
217 ( $1, $2);
218 $Elem eq "etp" && ($Dat{'error'} = 1);
219 my $Time = "";
220 $Data =~ m#<time>(.*?)</time># && ($Time = $1);
221 $Time =~ s{
222 (\d\d\d\d)-?(\d\d)-?(\d\d)T(\d\d):?(\d\d):?([\d\.]+?)Z
224 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'},
225 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}) =
226 ( $1, $2, $3,
227 $4, $5, $6);
229 }ex;
230 $Data =~ m#<lat>($DIGIT*?)</lat># && ($Dat{'lat'} = $1);
231 $Data =~ m#<lon>($DIGIT*?)</lon># && ($Dat{'lon'} = $1);
232 $Data =~ m#<ele>($DIGIT*?)</ele># && ($Dat{'ele'} = $1);
233 $Data =~ m#<desc>(.*?)</desc># && ($Dat{'desc'} = xml_to_txt($1));
234 print_entry(%Dat);
235 # }}}
236 } elsif (m#^<break\b.*?/>#) {
237 $found_move = 1;
238 } elsif (m#^<(desc|title|pause)\b.*?>(.*?)</(desc|title|pause)>#) {
239 $Dat{'type'} = $1;
240 $Dat{$1} = xml_to_txt($2);
241 print_entry(%Dat);
242 } elsif (/^<gpx\b/) {
243 $xml_data = $_;
244 $xml_data .= join("", <CurrFP>);
245 if (!length($Opt{'output-format'})) {
246 $Opt{'output-format'} = "gpx";
247 print_header(*STDOUT);
249 read_xmlfile($xml_data);
250 last;
251 } elsif (/^# Pause: /) {
252 $Opt{'print-comments'} && print;
253 } elsif (/^# move$/) {
254 $found_move = 1;
255 } elsif (/^#/) {
256 $Opt{'print-comments'} && print;
257 } elsif (m#^(\d+)\t($DIGIT+)\t($DIGIT+)\t($DIGIT)#) {
258 # CSV format, epoch style {{{
259 my ($ep_time, $lon_val, $lat_val, $Alt) =
260 ( $1, $2, $3, $4);
261 ($Dat{'sec'}, $Dat{'min'}, $Dat{'hour'},
262 $Dat{'day'}, $Dat{'month'}, $Dat{'year'},
263 $Dat{'wday'}, $Dat{'yday'}) = gmtime($ep_time);
264 $Dat{'month'}++; # Urgh Ⅰ
265 $Dat{'year'} += 1900; # Urgh Ⅱ
266 print_entry(%Dat);
267 # }}}
268 } elsif (m#^(\d\d\d\d)-?(\d\d)-?(\d\d)[T ](\d\d):?(\d\d):?(\d\d)Z?\t($DIGIT+)\t($DIGIT+)\t($DIGIT)#) {
269 # CSV format, human-readable date format {{{
270 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'},
271 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'},
272 $Dat{'lon'}, $Dat{'lat'}, $Dat{'ele'}) =
273 ($1, $2, $3,
274 $4, $5, $6,
275 $7, $8, $9);
276 print_entry(%Dat);
277 # }}}
278 } elsif (/^Trackpoint\t/) {
279 # 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 {{{
281 # Trackpoint\t
282 # N60.41630 E5.31675\t
283 # 09.02.2006 20:24:37 (UTC)\t
284 # 13.6 m\t
285 # \t
286 # 93.9 m\t
287 # 00:00:06\t
288 # 56 kph\t
289 # 123° true
290 my $Orig = $_;
291 $Orig =~ s/[\r\n]+$//;
292 my ($Marker_f, $Position_f, $Time_f, $Alt_f, $Depth_f,
293 $Leglength_f, $Legtime_f, $Legspeed_f, $Legcourse_f) =
294 split(/\t/, $Orig .
295 # Nødløsning for å unngå at variabler blir
296 # udefinert.
297 "\t\t\t\t\t\t\t\t\t\t"
299 D(join("",
300 "Position_f=\"$Position_f\" \x7B\x7B\x7B\n",
301 "Time_f=\"$Time_f\"\n",
302 "Alt_f=\"$Alt_f\"\n",
303 "Depth_f=\"$Depth_f\"\n",
304 "Leglength_f=\"$Leglength_f\"\n",
305 "Legtime_f=\"$Legtime_f\"\n",
306 "Legspeed_f=\"$Legspeed_f\"\n",
307 "Legcourse_f=\"$Legcourse_f\" \x7D\x7D\x7D\n",
309 my ($NS, $WE,
310 $Alt_unit,
311 $Leglength,
312 $Legtime_hour, $Legtime_min, $Legtime_sec,
313 $Legspeed, $Legspeed_unit,
314 $Legcourse
315 ) = ("", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
316 "", "", "", "", "", "", "", "");
317 ($Position_f =~ /^(N|S)([\d\.]+) (W|E)([\d\.]+)/) &&
318 ($NS = $1, $Dat{'lat'} = $2, $WE = $3, $Dat{'lon'} = $4);
319 ($Time_f =~ /^(\d+)\.(\d+)\.(\d+) (\d+):(\d+):(\d+) \((.+?)\)/) &&
320 ($Dat{'day'} = $1, $Dat{'month'} = $2, $Dat{'year'} = $3,
321 $Dat{'hour'} = $4, $Dat{'min'} = $5, $Dat{'sec'} = $6);
322 ($Alt_f =~ /^([\d+\.]+) (.*?)/) &&
323 ($Dat{'ele'} = $1, $Alt_unit = $2);
324 D("ele = \"$Dat{'ele'}\"");
325 ($NS eq "S") && ($Dat{'lat'} = 0-$Dat{'lat'});
326 ($WE eq "W") && ($Dat{'lon'} = 0-$Dat{'lon'});
327 # MapSource in win xp writes YYYY, but YY in win98se.
328 (defined($Dat{'year'}) && $Dat{'year'} =~ /\d/ && $Dat{'year'} < 1900) && ($Dat{'year'} += 2000);
329 print_entry(%Dat);
330 # }}}
331 } elsif (m#^T\t(\d\d)/(\d\d)/(\d\d\d\d) (\d\d):(\d\d):(\d\d)\t(.+)\xB0(.+)'(.+)"\t(.+)\xB0(.+)'(.+)"#) {
332 # T 09/01/2002 11:51:26 60°23'36.3" 5°19'35.9" {{{
333 my ($lat_d, $lat_m, $lat_s, $lon_d, $lon_m, $lon_s);
334 ($Dat{'month'}, $Dat{'day'}, $Dat{'year'},
335 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}, $lat_d,
336 $lat_m, $lat_s, $lon_d,
337 $lon_m, $lon_s) =
338 ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);
339 $Dat{'lat'} = sprintf("%.5f", 1*($lat_d+($lat_m/60)+($lat_s/3600)));
340 $Dat{'lon'} = sprintf("%.5f", $lon_d+($lon_m/60)+($lon_s/3600));
341 print_entry(%Dat);
342 # }}}
343 } elsif (m#^1 (\S+) (\S+) (\S+) (\S+) (\d\d)/(\d\d)/(\d\d\d\d) (\d\d):(\d\d):(\d\d)#) {
344 # 1 60.3938222 5.3238754 17.3 0 09/01/2002 14:18:23 {{{
345 ($Dat{'lat'}, $Dat{'lon'}, $Dat{'speed'},
346 $Dat{'unkn'},
347 $Dat{'month'}, $Dat{'day'}, $Dat{'year'},
348 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}) =
349 ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
350 print_entry(%Dat);
351 # }}}
352 } elsif (/^
353 # @020721221336N6048353E00701826S015-00001E4859N1673U0000 {{{
354 # Regexp {{{
355 (@) # @
356 (\d\d) # Year
357 (\d\d) # Month
358 (\d\d) # Day
359 (\d\d) # Hours
360 (\d\d) # Minutes
361 (\d\d) # Seconds
362 ([NS]) # N|S
363 (\d\d) # Latitude degree
364 (\d\d) # Latitude minute
365 (\d\d\d) # Latitude minute decimals
366 ([EW]) # E|W
367 (\d\d\d) # Longitude degree
368 (\d\d) # Longitude minute
369 (\d\d\d) # Longitude minute degree
370 (....) # Accurancy
371 (......) # Altitude
372 (...............)
374 # }}}
375 /x) {
376 my ($NS, $EW, $lat_deg, $lat_degmin, $lat_mindec, $lon_deg,
377 $lon_degmin, $lon_mindec);
378 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'}, $Dat{'hour'},
379 $Dat{'min'}, $Dat{'sec'}, $NS, $lat_deg,
380 $lat_degmin, $lat_mindec, $EW,
381 $lon_deg, $lon_degmin, $lon_mindec,
382 $Dat{'accur'}, $Dat{'ele'}, $Dat{'unknown'}) =
383 ($2+2000, $3, $4, $5, $6, $7, $8, $9, $10, $11,
384 $12, $13, $14, $15, $16, $17, $18);
385 my $ep_time = timegm_nocheck($Dat{'sec'}, $Dat{'min'}, $Dat{'hour'}, $Dat{'day'}, $Dat{'month'}-1, $Dat{'year'});
386 $last_time = $ep_time;
387 my $tmp_lon = sprintf("%.5f", $lon_deg + $lon_degmin/60 + $lon_mindec/60000);
388 my $tmp_lat = sprintf("%.5f", $lat_deg + $lat_degmin/60 + $lat_mindec/60000);
389 $tmp_lon =~ s/\./$Des/;
390 $tmp_lat =~ s/\./$Des/;
391 ($NS eq "S") && ($tmp_lat = 0-$tmp_lat);
392 ($EW eq "W") && ($tmp_lon = 0-$tmp_lon);
393 $Dat{'lat'} = $tmp_lat;
394 $Dat{'lon'} = $tmp_lon;
395 print_entry(%Dat);
396 # }}}
397 } elsif (/^(@)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(__________________________________________)/) {
398 # @020721221336__________________________________________ {{{
399 my ($Alfa, $Year, $Month, $Day, $Hour, $Min, $Sec, $Rest) =
400 ( $1, $2+2000, $3, $4, $5, $6, $7, $8);
401 $Opt{'output-format'} eq "csv" && print("\n");
402 $found_move = 1;
403 # }}}
404 } elsif (/^xmaplog /) {
405 ($Opt{'output-format'} eq "csv") && ($Opt{'save-to-file'} eq "\n") && print("\n");
406 } elsif (/^$/) {
407 ($Opt{'output-format'} eq "csv") && ($Opt{'save-to-file'} eq "\n") && print("\n");
408 } else {
409 if ($Opt{'print-comments'}) {
410 print("# $_");
411 chomp;
413 $Opt{'verbose'} && warn("Line $.: Unknown: \"$_\"\n");
416 # }}}
417 } else {
418 warn("$progname: $curr_file: Cannot open file for read: $!\n");
420 # }}}
423 print_footer(*STDOUT);
425 exit(0);
427 sub read_xmlfile {
428 # {{{
429 my $Txt = join("", @_);
430 # FIXME: The sequential stuff here is probably bad, but easy.
431 $Txt =~ s#(<gpx\b.*?>.*?</gpx>)#print_gpx($1)#gse;
432 $Txt =~ s#(<gps\b.*?>.*?</gps>)#print_xml_gps($1)#gse;
433 # }}}
436 sub print_gpx {
437 # {{{
438 my $Orig = shift;
439 my $Str = $Orig;
440 D("print_xml_gps(\"$Orig\")\n");
441 $Str =~
443 <trk\b(.*?)>(.*?)</trk>
446 my $el_trk = $2;
447 $el_trk =~
449 <trkseg\b(.*?)>(.*?)</trkseg>
452 my $el_trkseg = $2;
453 $el_trkseg =~
455 <trkpt\b(.*?)>(.*?)</trkpt>
458 my ($attr_trkpt, $el_trkpt) =
459 ( $1, $2);
460 ($attr_trkpt =~ /\blon="(.*?)"/) && ($Dat{'lon'} = $1);
461 ($attr_trkpt =~ /\blat="(.*?)"/) && ($Dat{'lat'} = $1);
462 ($el_trkpt =~ m#<ele\b.*?>(.*?)</ele>#) && ($Dat{'ele'} = $1);
463 if ($el_trkpt =~ m#<time>(\d\d\d\d)-?(\d\d)-?(\d\d)T(\d\d):?(\d\d):?(\d\d)\.?(\d*?)Z</time>#) {
464 ($Dat{'year'}, $Dat{'month'}, $Dat{'day'},
465 $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}, $Dat{'secfrac'}) =
466 ($1, $2, $3, $4, $5, $6, $7);
468 print_entry(%Dat);
470 }gsex;
471 $found_move = 1;
472 }gsex;
473 $found_move = 1;
474 }gsex;
475 # }}}
478 sub print_xml_gps {
479 # {{{
480 my $Orig = shift;
481 my $Str = $Orig;
482 D("print_xml_gps(\"$Orig\")\n");
483 if ($Str =~ m#<date>(\d\d\d\d)-?(\d\d)-?(\d\d)T(\d\d):?(\d\d):?(\d\d)\.?(\d*?)Z</date>#) {
484 ($Dat{'year'}, $Dat{'mon'}, $Dat{'day'}, $Dat{'hour'}, $Dat{'min'}, $Dat{'sec'}, $Dat{'secfrac'}) =
485 ( $1, $2, $3, $4, $5, $6, $7);
487 if ($Str =~ m#<pos>(.*?)</pos>#s) {
488 my $Txt = $1;
489 ($Txt =~ m#<x\b.*?>(.*?)</x>#) && ($Dat{'lon'} = $1);
490 ($Txt =~ m#<y\b.*?>(.*?)</y>#) && ($Dat{'lat'} = $1);
491 ($Txt =~ m#<z\b.*?>(.*?)</z>#) && ($Dat{'ele'} = $1);
493 defined($Dat{'lon'}) || ($Dat{'lon'} = "");
494 defined($Dat{'lat'}) || ($Dat{'lat'} = "");
495 defined($Dat{'ele'}) || ($Dat{'ele'} = "");
496 print_entry(%Dat);
497 # }}}
500 sub print_header {
501 # {{{
502 local *OutFP = shift;
503 if ($Opt{'output-format'} eq "gpsml") {
504 print(OutFP join("",
505 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
506 "<gpsml>\n",
507 "<track>\n",
509 } elsif ($Opt{'output-format'} eq "gpstrans") {
510 print(OutFP "Format: DMS UTC Offset: 0.00 hrs Datum[100]: WGS 84\n");
511 } elsif ($Opt{'output-format'} eq "gpx") {
512 print(OutFP join("",
513 "<?xml version=\"1.0\" standalone=\"no\"?>\n",
514 "<gpx>\n",
515 "$Spc$Spc<trk>\n",
516 "$Spc$Spc$Spc$Spc<trkseg>\n",
518 } elsif ($Opt{'output-format'} eq "ps") {
519 print(OutFP ps_header(532, 6034, 533, 6040));
520 print(OutFP "*u\n");
521 } elsif ($Opt{'output-format'} eq "xml") {
522 print(OutFP join("",
523 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
524 "<gpslog>\n",
526 } elsif ($Opt{'output-format'} eq "svg") {
527 print(OutFP join("",
528 "<?xml version=\"1.0\" standalone=\"no\"?>\n",
529 "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
530 "$Spc$Spc\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
531 "<svg height=\"1000\" width=\"1000\" viewBox=\"23 70 2 2\"\n",
532 "$Spc${Spc}xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n",
533 "$Spc$Spc<title></title>\n",
534 "$Spc$Spc<desc></desc>\n",
537 # }}}
540 sub print_footer {
541 # Print footer {{{
542 local *OutFP = shift;
543 if ($Opt{'output-format'} eq "gpsml") {
544 print(OutFP join("",
545 "</track>\n",
546 "</gpsml>\n",
548 } elsif ($Opt{'output-format'} eq "gpx") {
549 print(OutFP join("",
550 "$Spc$Spc$Spc$Spc</trkseg>\n",
551 "$Spc$Spc</trk>\n",
552 "</gpx>\n",
554 } elsif ($Opt{'output-format'} eq "poscount") {
555 while (my ($l_name, $l_val) = each %Poscount) {
556 $l_name =~ /^(.+?),(.+?)$/ && print(OutFP "$1\t$2\t$l_val\n");
558 } elsif ($Opt{'output-format'} eq "ps") {
559 print(OutFP join("",
560 "*U\n",
561 "%%Trailer\n",
562 "%%EOF\n",
564 } elsif ($Opt{'output-format'} eq "svg") {
565 print(OutFP "\"/>\n</svg>\n");
566 } elsif ($Opt{'output-format'} eq "xml") {
567 print(OutFP "</gpslog>\n");
569 # }}}
572 sub print_entry {
573 # Print a GPS entry with time, latitude, longitude and altitude in
574 # various formats
575 # {{{
576 my %Dat = @_;
577 my $print_time = length($Dat{'year'}) ? 1 : 0;
578 my $print_ele = length($Dat{'ele'}) ? 1 : 0;
579 my $print_desc = length($Dat{'desc'}) ? 1 : 0;
580 my $Line = "";
581 D("print_entry(\"" . join("\", \"", @_) . "\");");
582 my $ep_time;
584 if ($Opt{'near'}) {
585 $Line .= sprintf("%s ", list_nearest_waypoints($Dat{'lat'}, $Dat{'lon'}));
588 if ($Opt{'output-format'} eq "poscount") {
589 my ($Lat_str, $Lon_str) =
590 ( "", "");
591 $Dat{'lon'} =~ /^(\d+\.\d\d)/ && ($Lon_str = $1);
592 $Dat{'lat'} =~ /^(\d+\.\d\d)/ && ($Lat_str = $1);
593 my $Name = "${Lon_str},${Lat_str}";
594 defined($Poscount{$Name}) || ($Poscount{$Name} = 0);
595 $Poscount{$Name}++;
596 return;
599 if ($print_time) {
600 $ep_time = timegm_nocheck($Dat{'sec'}, $Dat{'min'}, $Dat{'hour'}, $Dat{'day'}, $Dat{'month'} - 1, $Dat{'year'});
601 $Dat{'year'} = sprintf("%04u", $Dat{'year'});
602 $Dat{'month'} = sprintf("%02u", $Dat{'month'});
603 $Dat{'day'} = sprintf("%02u", $Dat{'day'});
604 $Dat{'hour'} = sprintf("%02u", $Dat{'hour'});
605 $Dat{'min'} = sprintf("%02u", $Dat{'min'});
606 $Dat{'sec'} = sprintf("%02u", $Dat{'sec'});
607 if ($Opt{'chronology'}) {
608 if ($last_time > $ep_time) {
609 warn(sprintf(
610 "%s: \"%sZ\": Next date is %s in the past (%sZ)\n",
611 $progname, sec_to_string($last_time, "T"),
612 sec_to_readable($last_time-$ep_time),
613 sec_to_string($ep_time, "T")
615 # FIXME: Make --fix work with gpx and xml.
616 if ($Opt{'fix'} && ($Opt{'output-format'} !~ /^(gpx|xml)$/)) {
617 ($Line .= "# error ");
621 } else {
622 $Req{'time'} && return;
623 $ep_time = 0;
624 $Dat{'year'} = 0;
625 $Dat{'month'} = 0;
626 $Dat{'day'} = 0;
627 $Dat{'hour'} = 0;
628 $Dat{'min'} = 0;
629 $Dat{'sec'} = 0;
632 if ($Opt{'save-to-file'} ne "\n") {
633 # {{{
634 my $base_name = "$Dat{'year'}$Dat{'month'}$Dat{'day'}T$Dat{'hour'}$Dat{'min'}$Dat{'sec'}Z$Opt{'save-to-file'}";
635 my $file_name = $base_name;
636 if (-e $file_name) {
637 for (my $a = 1; (-e $file_name) && ($a < 1000); $a++) {
638 $file_name = "$base_name.dup_$a";
640 if (-e $file_name) {
641 die("$progname: $base_name: File already exists, and ran " .
642 "out of attempts to create unique file name\n");
644 if ($Opt{'verbose'}) {
645 warn("$progname: $base_name: File already exists, using " .
646 "unique name \"$file_name\" instead\n");
649 if (open(ToFP, ">", $file_name)) {
650 print_header(*ToFP);
651 print(ToFP ($from_stdin ? @first_lines : ()), (length($xml_data) ? $xml_data : <>)) ||
652 die("$progname: $file_name: Cannot write to file: $!\n");
653 print_footer(*ToFP);
654 close(ToFP);
655 if ($Opt{'output-format'} eq "gpsml") {
656 printf("<include>%s</include>\n",
657 txt_to_xml($file_name));
658 } elsif ($Opt{'output-format'} eq "gpx") {
659 printf("<!-- Saved unconverted data to \"%s\" -->\n",
660 txt_to_xml($file_name));
661 } else {
662 print("$progname: Saved unconverted data to \"$file_name\"\n");
664 exit 0;
665 } else {
666 die("$progname: $file_name: Cannot create file: $!\n");
668 # }}}
671 my $pause_len = 0;
672 my $do_print = 1;
673 ($Req{'altitude'} && !$print_ele) && return;
675 if ($Opt{'inside'} || $Opt{'outside'}) {
676 if (
677 ($Dat{'lat'} < $lat1) ||
678 ($Dat{'lat'} > $lat2) ||
679 ($Dat{'lon'} < $lon1) ||
680 ($Dat{'lon'} > $lon2)
682 $Opt{'inside'} && return;
683 } else {
684 $Opt{'outside'} && return;
688 if ($Opt{'comment-out-dups'}) {
689 if (($Dat{'lat'} eq $last_lat) && ($Dat{'lon'} eq $last_lon)) {
690 unless ($found_dup) {
691 $start_date = "$Dat{'year'}$Dat{'month'}$Dat{'day'}T$Dat{'hour'}$Dat{'min'}$Dat{'sec'}";
692 @Dup = ();
693 $found_dup = 1;
695 push(@Dup, "# $_");
696 $end_date = "$Dat{'year'}$Dat{'month'}$Dat{'day'}T$Dat{'hour'}$Dat{'min'}$Dat{'sec'}";
697 $do_print = 0;
698 } else {
699 if ($found_dup) {
700 print("# $start_date-$end_date: CO: No signal \x7B\x7B\x7B\n");
701 for (@Dup) {
702 print($_);
704 print("# $start_date-$end_date: CO: No signal \x7D\x7D\x7D\n# move\n$_");
705 $found_dup = 0;
706 } else {
707 $Line = $_;
708 $do_print = 1;
712 if ($Opt{'output-format'} eq "ps") {
713 $Dat{'lon'} *= 100;
714 $Dat{'lat'} *= 100;
716 # FIXME: $Opt{'skip_dups'} ble bytta ut med $Opt{'comment-out-dups'}
717 # i r583. Lurer på hva det gikk i der.
718 if ($Opt{'skip-dups'} && ($Dat{'lon'} eq $last_lon) && ($Dat{'lat'} eq $last_lat) && ($Dat{'ele'} eq $last_ele)) {
719 if ($in_dupskip) {
720 $do_print = 0;
721 } else {
722 $do_print = 1;
724 $in_dupskip = 1;
725 } else {
726 $do_print = 1;
727 $in_dupskip && ($Line .= $last_line);
728 $in_dupskip = 0;
731 if ($Opt{'create-breaks'} && $ep_time-$last_time > $PAUSE_LIMIT && $last_time) {
732 $pause_len = $ep_time-$last_time;
733 D("pause_len set to '$pause_len'");
736 if ($pause_len) {
737 if ($Opt{'output-format'} eq "gpsml") {
738 $Line .= sprintf("<pause>%s</pause>\n",
739 sec_to_readable($ep_time-$last_time));
740 } elsif ($Opt{'output-format'} eq "csv") {
741 $Line .= sprintf("# Pause: %s\n# move\n",
742 sec_to_readable($ep_time-$last_time));
746 if ($do_print) {
747 # Valid data was found, send to stdout {{{
748 if ($Opt{'double-y-scale'}) {
749 $Dat{'lat'} *= 2;
751 if ($Opt{'output-format'} eq "gpsml") {
752 if ($Dat{'type'} eq "tp") {
753 my $Elem = $Dat{'error'} ? "etp" : "tp";
754 $Line .= join("",
755 "<$Elem> ",
756 $print_time
757 ? "<time>$Dat{'year'}-$Dat{'month'}-$Dat{'day'}T" .
758 "$Dat{'hour'}:$Dat{'min'}:$Dat{'sec'}Z</time> "
759 : "",
760 (length($Dat{'lat'}))
761 ? "<lat>" . $Dat{'lat'}*1.0 . "</lat> "
762 : "",
763 (length($Dat{'lon'}))
764 ? "<lon>" . $Dat{'lon'}*1.0 . "</lon> "
765 : "",
766 ($print_ele)
767 ? "<ele>" . $Dat{'ele'}*1.0 . "</ele> "
768 : "",
769 ($print_desc)
770 ? sprintf("<desc>%s</desc> ",
771 txt_to_xml($Dat{'desc'}))
772 : "",
773 "</$Elem>\n"
775 } elsif ($Dat{'type'} =~ /^(pause|desc|title)$/) {
776 $Line .= sprintf("<%s>%s</%s>\n",
778 txt_to_xml($Dat{$1}),
779 $1);
781 } elsif ($Opt{'output-format'} eq "xgraph") {
782 $pause_len && ($Line .= "move ");
783 ($Line .= "$Dat{'lon'} $Dat{'lat'}\n");
784 } elsif($Opt{'output-format'} eq "gpstrans") {
785 my ($gpt_lat, $gpt_lon) = (ddd_to_dms($Dat{'lat'}), ddd_to_dms($Dat{'lon'}));
786 if ($print_time) {
787 $Line .= "T\t$Dat{'month'}/$Dat{'day'}/$Dat{'year'} $Dat{'hour'}:$Dat{'min'}:$Dat{'sec'}\t$gpt_lat\t$gpt_lon\n";
788 } else {
789 $Line .= "T\t00/00/00 00:00:00\t$gpt_lat\t$gpt_lon\n";
791 } elsif($Opt{'output-format'} eq "gpx") {
792 $Line .= join("",
793 "$Spc$Spc$Spc$Spc$Spc$Spc<trkpt lat=\"$Dat{'lat'}\" lon=\"$Dat{'lon'}\">$Spc",
794 $print_time
795 ? "<time>$Dat{'year'}-$Dat{'month'}-$Dat{'day'}T$Dat{'hour'}:$Dat{'min'}:$Dat{'sec'}Z</time>$Spc"
796 : "",
797 $print_ele
798 ? "<ele>$Dat{'ele'}</ele>$Spc"
799 : "",
800 "</trkpt>\n"
802 } elsif ($Opt{'output-format'} eq "clean") {
803 $pause_len && ($Line .= "\n");
804 ($Line .= "$Dat{'lon'}\t$Dat{'lat'}" . ($print_ele ? "\t$Dat{'ele'}" : "") . "\n");
805 } elsif ($Opt{'output-format'} eq "ps") {
806 $Line .= ($pause_len ? "f\n$Dat{'lon'} $Dat{'lat'} m\n" : "$Dat{'lon'} $Dat{'lat'} l\n");
807 } elsif ($Opt{'output-format'} eq "svg") {
808 $Line .= (
809 ($last_lon == 1000) || $pause_len
810 ? join("",
811 "$svg_start_thing<path\n",
812 " stroke=\"blue\"\n",
813 " stroke-width=\"0.001\"\n",
814 " fill=\"none\"\n",
815 " d=\"\n",
816 "M $Dat{'lon'} $Dat{'lat'}\n",
818 : "L $Dat{'lon'} $Dat{'lat'}\n"
820 } elsif ($Opt{'output-format'} eq "xml") {
821 $Line .= join("",
822 "$Spc$Spc<gps>$Spc",
823 $print_time
824 ? "<date>$Dat{'year'}-$Dat{'month'}-$Dat{'day'}T$Dat{'hour'}:$Dat{'min'}:$Dat{'sec'}Z</date>$Spc"
825 : "",
826 "<pos>$Spc",
827 (length($Dat{'lon'})) ? "<x>$Dat{'lon'}</x>$Spc" : "",
828 (length($Dat{'lat'})) ? "<y>$Dat{'lat'}</y>$Spc" : "",
829 ($print_ele) ? "<z>$Dat{'ele'}</z>$Spc" : "",
830 "</pos>$Spc",
831 "</gps>\n"
833 } elsif ($Opt{'output-format'} eq "ygraph") {
834 my $Time = $print_time ? ($ep_time - $first_time) * 1 : 0;
835 $Line .= "\"Time = $Time.0\n$Dat{'lon'} $Dat{'lat'}\n\n";
836 } elsif ($Opt{'output-format'} eq "csv") {
837 # {{{
838 $Dat{'lon'} =~ s/\./$Des/;
839 $Dat{'lat'} =~ s/\./$Des/;
840 # $do_print || print("skipping ");
841 $Line .= join("\t",
842 $print_time
843 ? $Opt{'epoch'}
844 ? $ep_time
845 : $Opt{'short-date'}
846 ? "$Dat{'year'}$Dat{'month'}$Dat{'day'}T$Dat{'hour'}$Dat{'min'}$Dat{'sec'}Z"
847 : "$Dat{'year'}-$Dat{'month'}-$Dat{'day'} $Dat{'hour'}:$Dat{'min'}:$Dat{'sec'}"
848 : "",
849 $Dat{'lon'},
850 $Dat{'lat'},
851 $print_ele ? $Dat{'ele'} : "", # Elevation
852 "\n"
854 # }}}
855 } else {
856 die("$progname: \"$Opt{'output-format'}\": Unknown output format\n");
858 # }}}
861 if (!$last_time && $Opt{'output-format'} eq "ps") {
862 $Line .= "$Dat{'lon'} $Dat{'lat'} m\n";
865 if ($do_print) {
866 if ($found_move) {
867 if ($Opt{'output-format'} eq "gpsml") {
868 $Line = "<break/>\n$Line";
870 (!$pause_len && ($Opt{'output-format'} eq "xgraph")) && ($Line .= "move $Line");
871 ($Opt{'output-format'} eq "clean") && ($Line .= "\n");
872 if ($Opt{'output-format'} eq "gpx") {
873 $Line .= "$Spc$Spc$Spc$Spc</trkseg>\n$Spc$Spc$Spc$Spc<trkseg>\n";
875 $found_move = 0;
877 print($Line);
879 $last_time = $ep_time;
880 $last_lon = $Dat{'lon'};
881 $last_lat = $Dat{'lat'};
882 $last_ele = $Dat{'ele'};
883 $last_line = $data_line;
884 $svg_start_thing = "\"/>\n";
885 # }}}
888 sub list_nearest_waypoints {
889 # {{{
890 my ($Lat, $Lon, $Count) = @_;
891 # FIXME: Incredible unfinished and kludgy.
892 if (open(WaypFP, "gpsbabel -i gpx -f $waypoint_file -x radius,lat=$Lat,lon=$Lon,distance=1000 -o gpx -F - |")) {
893 my $Str = join("", <WaypFP>);
894 $Str =~ s{
895 ^.*?<wpt\s.*?>.*?<name>(.+?)</name>.*?</wpt>.*?
896 .*?<wpt\s.*?>.*?<name>(.+?)</name>.*?</wpt>.*?
897 .*?<wpt\s.*?>.*?<name>(.+?)</name>.*?</wpt>.*$
899 "($1, $2, $3)";
900 }sex;
901 return($Str);
902 } else {
903 die("$progname: Cannot open gpsbabel pipe: $!\n");
905 # }}}
908 sub sec_to_string {
909 # Convert seconds since 1970 to "yyyy-mm-dd hh:mm:ss" with optional
910 # separator
911 # {{{
912 my ($Seconds, $Sep) = @_;
913 defined($Sep) || ($Sep = " ");
914 my @TA = gmtime($Seconds);
915 my($DateString) = sprintf("%04u-%02u-%02u%s%02u:%02u:%02u", $TA[5]+1900, $TA[4]+1, $TA[3], $Sep, $TA[2], $TA[1], $TA[0]);
916 return($DateString);
917 # }}}
920 sub sec_to_readable {
921 # Convert seconds since 1970 to human-readable format (d:hh:mm:ss)
922 # {{{
923 my $secs = shift;
924 D("sec_to_readable(\"$secs\")\n");
925 my ($Day, $Hour, $Min, $Sec) =
926 ( 0, 0, 0, 0);
928 $Day = int($secs/86400);
929 $secs -= $Day * 86400;
931 $Hour = int($secs/3600);
932 $secs -= $Hour * 3600;
934 $Min = int($secs/60);
935 $secs -= $Min * 60;
937 $Sec = $secs;
939 return(sprintf("%u:%02u:%02u:%02u", $Day, $Hour, $Min, $Sec));
940 # }}}
943 sub ps_header {
944 # Send a Postscript header to stdout {{{
945 my ($bl_lon, $bl_lat, $br_lon, $br_lat) = @_;
946 my $Date = sec_to_string(time);
947 return(join("",
948 "%!PS-Adobe-3.0 EPSF-3.0\n",
949 "%%Creator: $rcs_id\n",
950 "%%Title:\n",
951 "%%CreationDate: $Date\n",
952 "%%BoundingBox: $bl_lon $bl_lat $br_lon $br_lat\n",
953 "%%DocumentData: Clean7Bit\n",
954 "%%EndComments\n",
955 "%%BeginProlog\n",
956 "/bd { bind def } bind def\n",
957 "/incompound false def\n",
958 "/m { moveto } bd\n",
959 "/l { lineto } bd\n",
960 "/c { curveto } bd\n",
961 "/F { incompound not {fill} if } bd\n",
962 "/f { closepath F } bd\n",
963 "/S { stroke } bd\n",
964 "/*u { /incompound true def } bd\n",
965 "/*U { /incompound false def f} bd\n",
966 "/k { setcmykcolor } bd\n",
967 "/K { k } bd\n",
968 "%%EndProlog\n",
969 "%%BeginSetup\n",
970 "%%EndSetup\n",
972 # }}}
975 sub ddd_to_dms {
976 # Convert floating-point degrees into D°M'S.S" (ISO-8859-1).
977 # Necessary for import into GPSman. Based on toDMS() from
978 # gpstrans-0.39 to ensure compatibility.
979 # {{{
980 my $ddd = shift;
981 my $Neg = 0;
982 my ($Hour, $Min, $Sec) =
983 ( 0, 0, 0);
984 my $Retval = "";
986 if ($ddd < 0.0) {
987 $ddd = 0 - $ddd;
988 $Neg = 1;
990 $Hour = int($ddd);
991 $ddd = ($ddd - $Hour) * 60.0;
992 $Min = int($ddd);
993 $Sec = ($ddd - $Min) * 60.0;
995 if ($Sec > 59.5) {
996 $Sec = 0.0;
997 $Min += 1.0;
999 if ($Min > 59.5) {
1000 $Min = 0.0;
1001 $Hour += 1.0;
1003 if ($Neg) {
1004 $Hour = 0 - $Hour;
1006 D("Neg = $Neg , D = $Hour , M = $Min , S = $Sec\n");
1007 $Retval = sprintf("%s%.0f\xB0%02.0f'%04.1f\"", $Neg ? "-" : "", $Hour, $Min, $Sec);
1008 return $Retval;
1009 # }}}
1012 sub txt_to_xml {
1013 # Convert plain text to XML {{{
1014 my $Txt = shift;
1015 $Txt =~ s/&/&amp;/gs;
1016 $Txt =~ s/</&lt;/gs;
1017 $Txt =~ s/>/&gt;/gs;
1018 return($Txt);
1019 # }}}
1022 sub xml_to_txt {
1023 # Convert XML data to plain text {{{
1024 my $Txt = shift;
1025 $Txt =~ s/&lt;/</gs;
1026 $Txt =~ s/&gt;/>/gs;
1027 $Txt =~ s/&amp;/&/gs;
1028 return($Txt);
1029 # }}}
1032 sub print_version {
1033 # Print program version {{{
1034 print("$rcs_id\n");
1035 exit(0);
1036 # }}}
1037 } # print_version()
1039 sub usage {
1040 # Send the help message to stdout {{{
1041 my $Retval = shift;
1043 print(<<END);
1045 $rcs_id
1047 Converts between various GPS formats.
1049 Usage: $progname [options] [file [files [...]]]
1050 $progname -S [file [files [...]]]
1051 $progname -u [file [files [...]]]
1053 Options:
1055 -c, --comment-out-dups
1056 Use comma instead of period as decimal point (For Gnumeric etc).
1057 -C, --print-comments
1058 Print existing comment lines (starting with "#") and prefix unknown
1059 lines with "# ".
1060 --chronology
1061 Check for broken chronology, warn about entries with an old
1062 timestamp.
1063 -d, --skip-dups
1064 Skip duplicated coordinates, only print first and last.
1065 -e, --epoch
1066 Use seconds since 1970-01-01 00:00:00 GMT as date format.
1067 --fix
1068 Comment out entries which is obviously wrong. Use together with
1069 --chronology to fix those kind of errors. Does not work with GPX or
1070 XML output yet.
1071 -h, --help
1072 Show this help.
1073 --inside
1074 Print only trackpoints inside a rectangle specified by --pos1 and
1075 --pos2.
1076 -n x, --undefined x
1077 Use x as undefined value. Default: "$Udef".
1078 --near
1079 Add names of the three closest waypoints to the trackpoint.
1080 Unfinished and experimental, needs gpsbabel.
1081 -o x, --output-format x
1082 Use output format x:
1083 clean
1085 gpsml (Default)
1086 gpstrans
1087 gpx (Not complete)
1088 poscount (Experimental)
1089 ps (Unfinished)
1090 svg (Unfinished)
1091 xgraph
1093 ygraph
1094 --outside
1095 Print only trackpoints outside a rectangle specified by --pos1 and
1096 --pos2.
1097 --pos1 x, --pos2 x
1098 Specifies one corner where x is in "lat,lon" format (decimal
1099 degrees, negative for west or south) of area rectangle used by the
1100 --inside and --outside options.
1101 -r x, --require x
1102 Specify requirements for trackpoints to be written. x is a string
1103 with the following flags:
1105 Print only waypoints which have an altitude.
1107 Print only waypoints which have a timestamp.
1108 -s, --short-date
1109 Use short date format.
1110 -S x, --save-to-file x
1111 Save the unconverted data to a file with a filename starting with
1112 the timestamp of the first trackpoint. The parameter string x is
1113 added at the end of the filename. For the time being this option
1114 will ignore all other options. Note: If several files are specified
1115 on the command line, all data will be saved into only one file. This
1116 behaviour may change in the future.
1117 -t, --create-breaks
1118 Create breaks in track between points with a difference more than
1119 $PAUSE_LIMIT seconds.
1120 -u, --comment-out-dups
1121 Comment out following data with identical position values, only
1122 print first entry.
1123 -v, --verbose
1124 Verbose, warn about unknown lines.
1125 --version
1126 Print version information.
1127 -w, --strip-whitespace
1128 Strip all unnecessary whitespace.
1129 -y, --double-y-scale
1130 Double Y scale (latitude) to get it right in gnuplot.
1131 --debug
1132 Print debugging messages.
1135 exit($Retval);
1136 # }}}
1137 } # usage()
1139 sub D {
1140 # Print a debugging message {{{
1141 $Debug || return;
1142 my @call_info = caller;
1143 chomp(my $Txt = shift);
1144 my $File = $call_info[1];
1145 $File =~ s#\\#/#g;
1146 $File =~ s#^.*/(.*?)$#$1#;
1147 print(STDERR "$File:$call_info[2] $$ $Txt\n");
1148 return("");
1149 # }}}
1150 } # D()
1152 __END__
1154 # Plain Old Documentation (POD) {{{
1156 =pod
1158 =head1 NAME
1160 gptrans_conv
1162 =head1 REVISION
1164 $Id$
1166 =head1 SYNOPSIS
1168 B<gptrans_conv> [options] [file [files [...]]]
1170 B<gptrans_conv> -S [options] [file [files [...]]]
1172 B<gptrans_conv> -u [options] [file [files [...]]]
1174 =head1 DESCRIPTION
1176 Converts between various GPS formats.
1178 =head1 OPTIONS
1180 =over 4
1182 =item B<-c>, B<--comment-out-dups>
1184 Use comma instead of period as decimal point (For Gnumeric etc).
1186 =item B<-C>, B<--print-comments>
1188 Print existing comment lines (starting with "#") and prefix unknown
1189 lines with "# ".
1191 =item B<--chronology>
1193 Check for broken chronology, warn about entries with an old timestamp.
1195 =item B<-d>, B<--skip-dups>
1197 Skip duplicated coordinates, only print first and last.
1199 =item B<-e>, B<--epoch>
1201 Use seconds since 1970-01-01 00:00:00 GMT as date format.
1203 item B<--fix>
1205 Comment out entries which is obviously wrong. Use together with
1206 --chronology to fix those kind of errors. Does not work with GPX or XML
1207 output yet.
1209 =item B<-h>, B<--help>
1211 Show this help.
1213 =item B<--inside>
1215 Print only trackpoints inside a rectangle specified by --pos1 and
1216 --pos2.
1218 =item B<--near>
1220 Add names of the three closest waypoints to the trackpoint. Unfinished
1221 and experimental, needs gpsbabel.
1223 =item B<-n x>, B<--undefined x>
1225 Use x as undefined value.
1227 =item B<-o x>, B<--output-format x>
1229 Use output format x:
1231 =over 4
1233 =over 4
1235 =item clean
1237 =item csv
1239 =item gpsml (Default)
1241 This is the format which is meant to be used when storing the track
1242 logs.
1243 It is line-based XML which makes it easy to edit and grep. Probably not
1244 finished yet.
1246 =item gpstrans
1248 =item gpx (Not complete)
1250 =item poscount (Experimental)
1252 Creates a 3D plot where areas with many trackpoints are higher than
1253 areas with less track points.
1255 =item ps (Unfinished)
1257 =item svg (Unfinished)
1259 =item xgraph
1261 =item xml
1263 =item ygraph
1265 =back
1267 =back
1271 =item B<--outside>
1273 Print only trackpoints outside a rectangle specified by --pos1 and
1274 --pos2.
1276 =item B<--pos1 x>, B<--pos2 x>
1278 Specifies corners of an area rectangle used by the --inside and
1279 --outside options. The x value is in "lat,lon" format (decimal degrees,
1280 negative for west or south) .
1282 =item B<-r x>, B<--require x>
1284 Specify requirements for trackpoints to be written. x is a string with
1285 the following flags:
1287 =over 4
1289 =over 4
1291 =item a
1293 =over 4
1295 =item Print only waypoints which have an altitude.
1297 =back
1299 =back
1301 =over 4
1303 =item t
1305 =over 4
1307 =item Print only waypoints which have a timestamp.
1309 =back
1311 =back
1313 =back
1317 =item B<-s>, B<--short-date>
1319 Use short date format.
1321 =item B<-S x>, B<--save-to-file x>
1323 Save the unconverted data to a file with a filename starting with the
1324 timestamp of the first trackpoint. The parameter string x is added at
1325 the end of the filename. For the time being this option will ignore all
1326 other options.
1328 Note: If several files are specified on the command line, all data will
1329 be saved into only one file. This behaviour may change in the future.
1331 =item B<-t>, B<--create-breaks>
1333 Create breaks in track between points with a difference more than the
1334 number of seconds specified by the C<$PAUSE_LIMIT> variable.
1336 =item B<-u>, B<--comment-out-dups>
1338 Comment out following data with identical position values, only print
1339 first entry.
1341 =item B<-v>, B<--verbose>
1343 Verbose, warn about unknown lines.
1345 =item B<-w>, B<--strip-whitespace>
1347 Strip all unnecessary whitespace.
1349 =item B<-x>, B<--xml>
1351 Create XML output.
1353 =item B<-y>, B<--double-y-scale>
1355 Double Y scale (latitude) to get it right in gnuplot.
1357 =item B<-h>, B<--help>
1359 Print a brief help summary.
1361 =item B<--version>
1363 Print version information.
1365 =item B<--debug>
1367 Print debugging messages.
1369 =back
1371 =head1 BUGS
1373 Pretty incomplete in some areas. Some of the source formats are
1374 undocumented and thus incomplete. Some functionality is not working
1375 properly, for example the Postscript output.
1377 =head1 AUTHOR
1379 Made by Øyvind A. Holm S<E<lt>sunny@sunbase.orgE<gt>>.
1381 =head1 COPYRIGHT
1383 Copyleft © Øyvind A. Holm &lt;sunny@sunbase.org&gt;
1384 This is free software; see the file F<COPYING> for legalese stuff.
1386 =head1 LICENCE
1388 This program is free software; you can redistribute it and/or modify it
1389 under the terms of the GNU General Public License as published by the
1390 Free Software Foundation; either version 2 of the License, or (at your
1391 option) any later version.
1393 This program is distributed in the hope that it will be useful, but
1394 WITHOUT ANY WARRANTY; without even the implied warranty of
1395 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1396 See the GNU General Public License for more details.
1398 You should have received a copy of the GNU General Public License along
1399 with this program; if not, write to the Free Software Foundation, Inc.,
1400 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1402 =head1 SEE ALSO
1404 gpsbabel(1)
1406 =cut
1408 # }}}
1410 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :
1411 # End of file $Id$